From 883e6b6b49348dc230cb5c48d43f2deb2c3d1867 Mon Sep 17 00:00:00 2001 From: Andrew Berry Date: Thu, 8 Oct 2026 15:07:31 -0400 Subject: [PATCH] chore: migrate AI Task Manager to Strikethroo Move existing plans and tasks into the Strikethroo workspace and replace legacy commands and scripts with current workflow skills for Claude and Codex. --- .agents/skills/st-code-review/SKILL.md | 52 + .../references/review-example.xml.md | 18 + .../st-code-review/scripts/code-review.cjs | 4303 +++++++++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .agents/skills/st-create-plan/SKILL.md | 111 + .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/get-next-plan-id.cjs | 199 + .agents/skills/st-execute-blueprint/SKILL.md | 198 + .../scripts/capture-base-commit.cjs | 342 ++ .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/check-phase-readiness.cjs | 3059 ++++++++++++ .../scripts/create-feature-branch.cjs | 386 ++ .../scripts/dispatch-task-execution.cjs | 3688 ++++++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .agents/skills/st-execute-task/SKILL.md | 154 + .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/check-task-dependencies.cjs | 3042 ++++++++++++ .../scripts/dispatch-task-execution.cjs | 3688 ++++++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .agents/skills/st-full-workflow/SKILL.md | 473 ++ .../references/complexity-rubric.md | 8 + .../scripts/capture-base-commit.cjs | 342 ++ .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/check-phase-readiness.cjs | 3059 ++++++++++++ .../scripts/create-feature-branch.cjs | 386 ++ .../scripts/dispatch-task-execution.cjs | 3688 ++++++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/get-next-plan-id.cjs | 199 + .../scripts/get-next-task-id.cjs | 303 ++ .../scripts/route-task-execution.cjs | 3138 ++++++++++++ .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .agents/skills/st-generate-tasks/SKILL.md | 218 + .../references/complexity-rubric.md | 8 + .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/get-next-task-id.cjs | 303 ++ .../scripts/route-task-execution.cjs | 3138 ++++++++++++ .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .agents/skills/st-refine-plan/SKILL.md | 132 + .../scripts/check-for-updates.cjs | 2634 ++++++++++ .../scripts/find-strikethroo-root.cjs | 118 + .../scripts/validate-plan-blueprint.cjs | 1508 ++++++ .ai/strikethroo/.gitignore | 33 + .ai/strikethroo/.init-metadata.json | 33 + .ai/strikethroo/README.md | 7 + .../config/STRIKETHROO.md} | 16 +- .ai/strikethroo/config/hooks/CODE_REVIEW.md | 50 + .../config/hooks/POST_ERROR_DETECTION.md | 4 +- .../config/hooks/POST_EXECUTION.md | 5 + .../config/hooks/POST_PHASE.md | 9 +- .ai/strikethroo/config/hooks/POST_PLAN.md | 5 + .../config/hooks/POST_TASK_GENERATION_ALL.md | 31 + .ai/strikethroo/config/hooks/PRE_PHASE.md | 8 + .../config/hooks/PRE_PLAN.md | 4 +- .../config/hooks/PRE_TASK_ASSIGNMENT.md | 32 +- .../config/hooks/PRE_TASK_EXECUTION.md | 15 + .../config/hooks/TASK_EXECUTION_ROUTING.md | 30 + .../config/schemas/self-review-v2.xsd | 416 ++ .../config/shared/anti-rationalization.md | 3 + .../config/shared/clarification-gate.md | 7 + .../config/shared/verification-gate.md | 10 + .../config/templates/BLUEPRINT_TEMPLATE.md | 2 - .../templates/EXECUTION_SUMMARY_TEMPLATE.md | 2 +- .../config/templates/PLAN_TEMPLATE.md | 2 +- .../config/templates/TASK_TEMPLATE.md | 5 +- .../templates/UPDATE_NOTICE_TEMPLATE.md | 1 + .../plan-01--review-open-issues.md | 0 .../tasks/01--improve-install-playwright.md | 0 .../tasks/02--document-show-report.md | 0 .../tasks/03--prepare-locale-feedback.md | 0 .../plan-02--ci-standard-test-template.md | 0 .ai/task-manager/.init-metadata.json | 19 - .ai/task-manager/README.md | 7 - .ai/task-manager/config/hooks/POST_PLAN.md | 3 - .../config/hooks/POST_TASK_GENERATION_ALL.md | 41 - .ai/task-manager/config/hooks/PRE_PHASE.md | 43 - .../scripts/check-task-dependencies.cjs | 240 - .../config/scripts/compose-prompt.cjs | 234 - .../config/scripts/create-feature-branch.cjs | 204 - .../config/scripts/extract-task-skills.cjs | 84 - .ai/task-manager/config/scripts/find-root.cjs | 10 - .../config/scripts/get-next-plan-id.cjs | 49 - .../config/scripts/get-next-task-id.cjs | 81 - .../config/scripts/shared-utils.cjs | 418 -- .../scripts/validate-plan-blueprint.cjs | 138 - .claude/agents/plan-creator.md | 6 +- .claude/commands/tasks/create-plan-auto.md | 174 - .claude/commands/tasks/create-plan.md | 172 - .claude/commands/tasks/execute-blueprint.md | 230 - .claude/commands/tasks/execute-task.md | 348 -- .claude/commands/tasks/fix-broken-tests.md | 44 - .claude/commands/tasks/full-workflow.md | 840 ---- .claude/commands/tasks/generate-tasks.md | 348 -- .claude/commands/tasks/refine-plan-auto.md | 172 - .claude/commands/tasks/refine-plan.md | 163 - .claude/skills/st-code-review | 1 + .claude/skills/st-create-plan | 1 + .claude/skills/st-execute-blueprint | 1 + .claude/skills/st-execute-task | 1 + .claude/skills/st-full-workflow | 1 + .claude/skills/st-generate-tasks | 1 + .claude/skills/st-refine-plan | 1 + .codex/agents/plan-creator.toml | 93 + skills-lock.json | 47 + 108 files changed, 61144 insertions(+), 4114 deletions(-) create mode 100644 .agents/skills/st-code-review/SKILL.md create mode 100644 .agents/skills/st-code-review/references/review-example.xml.md create mode 100755 .agents/skills/st-code-review/scripts/code-review.cjs create mode 100644 .agents/skills/st-code-review/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-code-review/scripts/validate-plan-blueprint.cjs create mode 100644 .agents/skills/st-create-plan/SKILL.md create mode 100644 .agents/skills/st-create-plan/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-create-plan/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-create-plan/scripts/get-next-plan-id.cjs create mode 100644 .agents/skills/st-execute-blueprint/SKILL.md create mode 100644 .agents/skills/st-execute-blueprint/scripts/capture-base-commit.cjs create mode 100644 .agents/skills/st-execute-blueprint/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs create mode 100644 .agents/skills/st-execute-blueprint/scripts/create-feature-branch.cjs create mode 100755 .agents/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs create mode 100644 .agents/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs create mode 100644 .agents/skills/st-execute-task/SKILL.md create mode 100644 .agents/skills/st-execute-task/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-execute-task/scripts/check-task-dependencies.cjs create mode 100755 .agents/skills/st-execute-task/scripts/dispatch-task-execution.cjs create mode 100644 .agents/skills/st-execute-task/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-execute-task/scripts/validate-plan-blueprint.cjs create mode 100644 .agents/skills/st-full-workflow/SKILL.md create mode 100644 .agents/skills/st-full-workflow/references/complexity-rubric.md create mode 100644 .agents/skills/st-full-workflow/scripts/capture-base-commit.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/check-phase-readiness.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/create-feature-branch.cjs create mode 100755 .agents/skills/st-full-workflow/scripts/dispatch-task-execution.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/get-next-plan-id.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/get-next-task-id.cjs create mode 100755 .agents/skills/st-full-workflow/scripts/route-task-execution.cjs create mode 100644 .agents/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs create mode 100644 .agents/skills/st-generate-tasks/SKILL.md create mode 100644 .agents/skills/st-generate-tasks/references/complexity-rubric.md create mode 100644 .agents/skills/st-generate-tasks/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-generate-tasks/scripts/get-next-task-id.cjs create mode 100755 .agents/skills/st-generate-tasks/scripts/route-task-execution.cjs create mode 100644 .agents/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs create mode 100644 .agents/skills/st-refine-plan/SKILL.md create mode 100644 .agents/skills/st-refine-plan/scripts/check-for-updates.cjs create mode 100644 .agents/skills/st-refine-plan/scripts/find-strikethroo-root.cjs create mode 100644 .agents/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs create mode 100644 .ai/strikethroo/.gitignore create mode 100644 .ai/strikethroo/.init-metadata.json create mode 100644 .ai/strikethroo/README.md rename .ai/{task-manager/config/TASK_MANAGER.md => strikethroo/config/STRIKETHROO.md} (85%) create mode 100644 .ai/strikethroo/config/hooks/CODE_REVIEW.md rename .ai/{task-manager => strikethroo}/config/hooks/POST_ERROR_DETECTION.md (86%) rename .ai/{task-manager => strikethroo}/config/hooks/POST_EXECUTION.md (72%) rename .ai/{task-manager => strikethroo}/config/hooks/POST_PHASE.md (72%) create mode 100644 .ai/strikethroo/config/hooks/POST_PLAN.md create mode 100644 .ai/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md create mode 100644 .ai/strikethroo/config/hooks/PRE_PHASE.md rename .ai/{task-manager => strikethroo}/config/hooks/PRE_PLAN.md (89%) rename .ai/{task-manager => strikethroo}/config/hooks/PRE_TASK_ASSIGNMENT.md (51%) create mode 100644 .ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md create mode 100644 .ai/strikethroo/config/hooks/TASK_EXECUTION_ROUTING.md create mode 100644 .ai/strikethroo/config/schemas/self-review-v2.xsd create mode 100644 .ai/strikethroo/config/shared/anti-rationalization.md create mode 100644 .ai/strikethroo/config/shared/clarification-gate.md create mode 100644 .ai/strikethroo/config/shared/verification-gate.md rename .ai/{task-manager => strikethroo}/config/templates/BLUEPRINT_TEMPLATE.md (87%) rename .ai/{task-manager => strikethroo}/config/templates/EXECUTION_SUMMARY_TEMPLATE.md (94%) rename .ai/{task-manager => strikethroo}/config/templates/PLAN_TEMPLATE.md (96%) rename .ai/{task-manager => strikethroo}/config/templates/TASK_TEMPLATE.md (82%) create mode 100644 .ai/strikethroo/config/templates/UPDATE_NOTICE_TEMPLATE.md rename .ai/{task-manager => strikethroo}/plans/01--review-open-issues/plan-01--review-open-issues.md (100%) rename .ai/{task-manager => strikethroo}/plans/01--review-open-issues/tasks/01--improve-install-playwright.md (100%) rename .ai/{task-manager => strikethroo}/plans/01--review-open-issues/tasks/02--document-show-report.md (100%) rename .ai/{task-manager => strikethroo}/plans/01--review-open-issues/tasks/03--prepare-locale-feedback.md (100%) rename .ai/{task-manager => strikethroo}/plans/02--ci-standard-test-template/plan-02--ci-standard-test-template.md (100%) delete mode 100644 .ai/task-manager/.init-metadata.json delete mode 100644 .ai/task-manager/README.md delete mode 100644 .ai/task-manager/config/hooks/POST_PLAN.md delete mode 100644 .ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md delete mode 100644 .ai/task-manager/config/hooks/PRE_PHASE.md delete mode 100755 .ai/task-manager/config/scripts/check-task-dependencies.cjs delete mode 100755 .ai/task-manager/config/scripts/compose-prompt.cjs delete mode 100644 .ai/task-manager/config/scripts/create-feature-branch.cjs delete mode 100644 .ai/task-manager/config/scripts/extract-task-skills.cjs delete mode 100755 .ai/task-manager/config/scripts/find-root.cjs delete mode 100644 .ai/task-manager/config/scripts/get-next-plan-id.cjs delete mode 100644 .ai/task-manager/config/scripts/get-next-task-id.cjs delete mode 100644 .ai/task-manager/config/scripts/shared-utils.cjs delete mode 100755 .ai/task-manager/config/scripts/validate-plan-blueprint.cjs delete mode 100644 .claude/commands/tasks/create-plan-auto.md delete mode 100644 .claude/commands/tasks/create-plan.md delete mode 100644 .claude/commands/tasks/execute-blueprint.md delete mode 100644 .claude/commands/tasks/execute-task.md delete mode 100644 .claude/commands/tasks/fix-broken-tests.md delete mode 100644 .claude/commands/tasks/full-workflow.md delete mode 100644 .claude/commands/tasks/generate-tasks.md delete mode 100644 .claude/commands/tasks/refine-plan-auto.md delete mode 100644 .claude/commands/tasks/refine-plan.md create mode 120000 .claude/skills/st-code-review create mode 120000 .claude/skills/st-create-plan create mode 120000 .claude/skills/st-execute-blueprint create mode 120000 .claude/skills/st-execute-task create mode 120000 .claude/skills/st-full-workflow create mode 120000 .claude/skills/st-generate-tasks create mode 120000 .claude/skills/st-refine-plan create mode 100644 .codex/agents/plan-creator.toml create mode 100644 skills-lock.json diff --git a/.agents/skills/st-code-review/SKILL.md b/.agents/skills/st-code-review/SKILL.md new file mode 100644 index 0000000..09f7cf6 --- /dev/null +++ b/.agents/skills/st-code-review/SKILL.md @@ -0,0 +1,52 @@ +--- +name: st-code-review +description: Use when the blueprint execution gate asks for an independent second-harness review of a Strikethroo plan's cumulative diff in this repository — triggers include code review gate, review the plan diff, second-model review, CODE_REVIEW hook, review the cumulative diff. Do not use to review a single task, to review code outside a Strikethroo plan, or to give general code-quality or style opinions. +--- + + + +# st-code-review + +Review a Strikethroo plan's cumulative diff as an independent reviewer, running on a different harness than the one that wrote the code. `` is the workspace root the dispatch supplies. + +Your findings are recorded, not applied. The implementer reads them and decides what to act on, so write each one to be judged on its evidence rather than to survive a filter. + +## Anti-rationalization + +Read `/config/shared/anti-rationalization.md`. Every row below is an excuse you will be tempted to make. + +| You catch yourself thinking... | The binding rule | +| --- | --- | +| "This could theoretically fail if..." | Name the concrete input or state, or it is not a finding. | +| "The plan does not say this, but it should have." | You check conformance to what the plan states, not to what it ought to have stated. | +| "This works, but the abstraction is wrong." | Design opinion. Record nothing. | +| "I am unsure, so I will justify at length to be safe." | Length is not evidence. Lower `confidence` instead. | +| "The caller probably handles this." / "...probably does not." | An unread caller is an assumption. Read it, or mark `confidence="medium"` and state the assumption in the body. | +| "Only `minor`, but real, so I will call it `major` so someone acts on it." | Severity is impact. Inflating it corrupts the one signal the reader sorts by. | +| "I found nothing, so I should look harder until this produces something." | A clean diff is a valid result. Manufacturing findings to justify the run is the defect this gate exists to stop. | + +## Output + +Emit one document in the `urn:self-review:v2` namespace that validates against `/config/schemas/self-review-v2.xsd`. Give every changed file its own `` element, including the ones you read and had no comment on, with a repository-relative `path`. Give each comment exactly one line pair: `new-line-*` for added or context lines, `old-line-*` for deleted ones, neither for a file-level comment, start equal to end for a single line. Read `references/review-example.xml.md` before emitting. + +**Never emit a ``.** The element exists so that a human reviewer can hand the implementer exact replacement text, and whatever it contains gets applied verbatim, without anyone reading it first. You are not a human reviewer. Describe the fix in the `` and leave the writing of it to the implementer. + +## Operating Procedure + +Each step ends only when its exit criterion holds. + +1. **Read `/config/hooks/CODE_REVIEW.md`.** It is authoritative and beats this prompt wherever they disagree. Exit: you can state the finding categories in scope from that file. +2. **Read the dispatched plan in full.** Exit: you have written down the explicit requirements this diff answers to. Nothing off that list can produce a `requirement-conformance` finding. +3. **Read the cumulative diff.** Compare the base commit against the **current working tree** using `git diff `, never `..HEAD`, which misses uncommitted work. Read the whole diff. You run once, so never schedule, request, or simulate a second pass. Exit: every changed file is enumerated and will get a `` element. +4. **Run the blast-radius pass.** Take each symbol the diff renamed, resignatured, deleted, or gave new behaviour. Search the repository and read every hit outside the diff. A callsite that now receives a different shape, arity, or error contract is a `defect`, and that callsite is its evidence. This is targeted expansion, not whole-codebase review. Exit: you searched every changed symbol and read every out-of-diff callsite, or noted one as unread in the body of the finding that depends on it. +5. **Critique each candidate.** Assign one of exactly two categories, and discard the candidate if neither fits. `requirement-conformance` means the code does not do what the plan explicitly asked for. `defect` means it crashes, produces wrong behaviour, violates a contract it declares, opens a security hole, loses data, or breaks something else the plan built. Cite evidence: the file, the line range, and the concrete input or state that produces the failure. Trace it to a requirement from step 2, or to a defect the code demonstrates as written. Grade `severity` and `confidence` against the mandate hook read in step 1. Attach no ``. Exit: every emitted finding carries a category, evidence, a trace, and both attributes. Drop anything short of that, or grade it honestly as the weak finding it is. +6. **Emit the document.** Exit: it declares `urn:self-review:v2`, has one `` per changed file, and every `` carries both attributes. +7. **Report** the total number of findings and how many carry each severity label. Exit: the counts match the document. Never claim a clean review without having emitted it. + +**Out of mandate.** Record nothing for speculative hardening, and nothing for tests the plan never asked for. Missing "this works, matches the plan, and has the wrong abstraction" is deliberate. Do not widen scope to recover it. + +**Failure modes.** Cannot read the plan: stop and report, and never review against requirements you reconstructed. Empty diff: emit `` with no children and report zero findings, which counts as success. A finding will not fit the schema: fix the shape of the finding, never the schema. Tempted to apply a fix yourself: stop, because detection and remediation run on separate routes by design. diff --git a/.agents/skills/st-code-review/references/review-example.xml.md b/.agents/skills/st-code-review/references/review-example.xml.md new file mode 100644 index 0000000..afed98b --- /dev/null +++ b/.agents/skills/st-code-review/references/review-example.xml.md @@ -0,0 +1,18 @@ +# Review document example + +A complete document that validates against `/config/schemas/self-review-v2.xsd`. + +```xml + + + + + Plan requirement "reject an empty id" is unmet: parseId("") returns + `{ ok: true }` because the length guard runs after the early return. + requirement-conformance + + + + +``` diff --git a/.agents/skills/st-code-review/scripts/code-review.cjs b/.agents/skills/st-code-review/scripts/code-review.cjs new file mode 100755 index 0000000..93a84ae --- /dev/null +++ b/.agents/skills/st-code-review/scripts/code-review.cjs @@ -0,0 +1,4303 @@ +#!/usr/bin/env node +// Review-category modelling and false-positive suppression heuristics in +// this skill draw on PR-Agent (https://github.com/The-PR-Agent/pr-agent), +// used under its permissive licence. No PR-Agent code is vendored. +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/code-review.ts +var code_review_exports = {}; +__export(code_review_exports, { + _classify: () => _classify, + _extractReviewDocument: () => _extractReviewDocument, + _makeDeliveryToken: () => _makeDeliveryToken, + _readBaseCommit: () => _readBaseCommit, + _readCumulativeDiff: () => _readCumulativeDiff, + _resultLine: () => _resultLine, + buildReviewerPrompt: () => buildReviewerPrompt, + createFindingsGate: () => createFindingsGate, + main: () => main, + runReview: () => runReview +}); +module.exports = __toCommonJS(code_review_exports); +var crypto = __toESM(require("crypto")); +var fs7 = __toESM(require("fs")); +var path8 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/git-utils.ts +var import_child_process = require("child_process"); +var GIT_OUTPUT_LIMIT = 64 * 1024 * 1024; +var run = (args, opts) => (0, import_child_process.execFileSync)("git", [...args], { + cwd: opts.cwd, + input: opts.input, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: GIT_OUTPUT_LIMIT +}); +var execGit = (args, opts = {}) => { + try { + const out = run(args, opts); + return opts.trim === false ? out : out.trim(); + } catch { + return null; + } +}; +var execGitDiffAllowingChanges = (args, opts = {}) => { + try { + return run(args, opts); + } catch (error) { + const failure = error; + if (failure.status === 1 && typeof failure.stdout === "string" && failure.stdout.length > 0) { + return failure.stdout; + } + return null; + } +}; +var splitNulDelimited = (listing) => listing.split("\0").filter((entry) => entry.length > 0); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/harness-availability.ts +var import_crypto2 = require("crypto"); +var import_child_process3 = require("child_process"); +var fs6 = __toESM(require("fs")); +var os = __toESM(require("os")); +var path7 = __toESM(require("path")); + +// src/skill-scripts/shared/harness-configuration.ts +var import_crypto = require("crypto"); +var fs4 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/execution-routing.ts +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); + +// src/skill-scripts/shared/harness-configuration.ts +var HARNESS_CONFIGURATION_SECTION = "harnesses"; +var HARNESS_CONFIGURATION_NORMALIZATION_VERSION = 1; +var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var hashHarnessCliArgs = (harness, cliArgs, normalizationVersion = HARNESS_CONFIGURATION_NORMALIZATION_VERSION) => (0, import_crypto.createHash)("sha256").update( + JSON.stringify({ + schema: normalizationVersion, + harness, + cliArgs + }), + "utf8" +).digest("hex"); +var normalizeInvocation = (harness, cliArgs) => { + const immutableArgs = Object.freeze([...cliArgs]); + return Object.freeze({ + cliArgs: immutableArgs, + cliArgsHash: hashHarnessCliArgs(harness, immutableArgs) + }); +}; +var emptyConfiguration = () => Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, normalizeInvocation(harness, [])]) + ) +); +var validateHarnessEntry = (harness, raw, errors) => { + const entryPath = `config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness}`; + if (!isPlainObject2(raw)) { + errors.push(`${entryPath} must be a mapping.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "cli_args") errors.push(`${entryPath}.${key} is not supported.`); + } + if (!("cli_args" in raw)) return normalizeInvocation(harness, []); + if (!Array.isArray(raw.cli_args)) { + errors.push(`${entryPath}.cli_args must be an array of exact strings.`); + return null; + } + const cliArgs = []; + raw.cli_args.forEach((value, index) => { + const valuePath = `${entryPath}.cli_args[${index}]`; + if (typeof value !== "string" || value.length === 0) { + errors.push(`${valuePath} must be a non-empty string.`); + return; + } + if (value.includes("\0")) { + errors.push(`${valuePath} must not contain a NUL character.`); + return; + } + cliArgs.push(value); + }); + return normalizeInvocation(harness, cliArgs); +}; +var loadHarnessConfiguration = (strikethrooRoot) => { + const configPath = path5.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs4.readFileSync(configPath, "utf8"); + } catch (error) { + if (error.code === "ENOENT") { + return { kind: "config", config: emptyConfiguration() }; + } + return { + kind: "invalid", + errors: [ + `config.yaml could not be read: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (!hasYamlContent(contents)) return { kind: "config", config: emptyConfiguration() }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject2(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[HARNESS_CONFIGURATION_SECTION]; + if (section === null || section === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject2(section)) { + return { + kind: "invalid", + errors: [`config.yaml ${HARNESS_CONFIGURATION_SECTION} must be a YAML mapping.`] + }; + } + const errors = []; + const supportedHarnesses = new Set(SUPPORTED_HARNESSES); + for (const harness of Object.keys(section)) { + if (!supportedHarnesses.has(harness)) { + errors.push(`config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness} is not supported.`); + } + } + const entries = {}; + for (const harness of SUPPORTED_HARNESSES) { + if (!(harness in section)) { + entries[harness] = normalizeInvocation(harness, []); + continue; + } + const entry = validateHarnessEntry(harness, section[harness], errors); + if (entry) entries[harness] = entry; + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "config", config: Object.freeze(entries) }; +}; + +// src/skill-scripts/shared/executable-resolution.ts +var fs5 = __toESM(require("fs")); +var path6 = __toESM(require("path")); +var DEFAULT_PATHEXT = ".EXE;.CMD;.BAT;.COM"; +var hasPathSeparator = (executable) => /[\\/]/.test(executable); +var resolveExecutablePath = (executable, environment = {}) => { + const env = environment.env ?? process.env; + const platform = environment.platform ?? process.platform; + const win32 = platform === "win32"; + const suffixes = win32 ? ["", ...(env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean)] : [""]; + const directories = hasPathSeparator(executable) ? [""] : (env.PATH ?? "").split(path6.delimiter).filter(Boolean); + const mode = win32 ? fs5.constants.F_OK : fs5.constants.X_OK; + for (const directory of directories) { + for (const suffix of suffixes) { + const candidate = path6.resolve(directory, `${executable}${suffix}`); + try { + fs5.accessSync(candidate, mode); + if (fs5.statSync(candidate).isFile()) return fs5.realpathSync(candidate); + } catch { + } + } + } + return null; +}; +var executableResolves = (executable, environment) => resolveExecutablePath(executable, environment) !== null; + +// src/skill-scripts/shared/external-dispatch.ts +var import_child_process2 = require("child_process"); +var command = (executable, argv, request) => ({ + executable, + argv, + cwd: request.workspace, + stdin: request.prompt +}); +var modelArgv = (model) => model === void 0 ? [] : ["--model", model]; +var EXTERNAL_HARNESS_ADAPTERS = { + claude: { + executable: "claude", + buildCommand: (request) => command( + "claude", + [ + "-p", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--effort", request.reasoningEffort] + ], + request + ), + authenticationArgv: () => ["auth", "status"] + }, + codex: { + executable: "codex", + buildCommand: (request) => command( + "codex", + [ + "exec", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--config", `model_reasoning_effort=${request.reasoningEffort}`], + "-" + ], + request + ), + authenticationArgv: () => ["login", "status"] + }, + cursor: { + executable: "cursor-agent", + buildCommand: (request) => command( + "cursor-agent", + ["--print", ...request.cliArgs, ...modelArgv(request.model)], + request + ), + authenticationArgv: () => ["status"] + }, + gemini: { + executable: "gemini", + // The empty positional prompt is the existing contract — content travels on + // stdin. It stays even when the model pair is dropped. + buildCommand: (request) => command("gemini", ["--prompt", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + copilot: { + executable: "copilot", + buildCommand: (request) => command("copilot", ["-p", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + opencode: { + executable: "opencode", + buildCommand: (request) => command( + "opencode", + [ + "run", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--variant", request.reasoningEffort], + "-" + ], + request + ), + authenticationArgv: () => ["auth", "list"] + } +}; +var adapterKeys = Object.keys(EXTERNAL_HARNESS_ADAPTERS).sort(); +var harnessKeys = [...SUPPORTED_HARNESSES].sort(); +if (adapterKeys.join("\0") !== harnessKeys.join("\0")) { + throw new Error("External harness adapter registry does not cover SUPPORTED_HARNESSES exactly."); +} +var reviewCommandRequest = (request) => ({ + cliArgs: request.cliArgs ?? [], + workspace: request.workspace, + prompt: request.prompt +}); +var CAPTURED_STDOUT_LIMIT = 262144; +var AUTHENTICATION_TIMEOUT_MS = 3e4; +var STDIO_SLOTS = { + ignore: { stdout: "ignore" }, + inherit: { stdout: "inherit" }, + capture: { stdout: "pipe" } +}; +var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore", timeoutMs) => new Promise((resolve4, reject) => { + let settled = false; + const child = (0, import_child_process2.spawn)(executable, argv, { + cwd, + shell: false, + stdio: [ + stdin === void 0 ? "ignore" : "pipe", + STDIO_SLOTS[outputMode].stdout, + outputMode === "ignore" ? "ignore" : "inherit" + ] + }); + const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => { + if (settled) return; + settled = true; + child.kill("SIGKILL"); + resolve4({ exitCode: 1, timedOut: true }); + }, timeoutMs); + const settle = (outcome2) => { + if (settled) return; + settled = true; + clearTimeout(timer); + resolve4(outcome2); + }; + const fail = (error) => { + if (settled) return; + settled = true; + clearTimeout(timer); + reject(error); + }; + let captured = ""; + if (outputMode === "capture") { + child.stdout.setEncoding("utf8"); + child.stdout.once("error", fail); + child.stdout.on("data", (chunk) => { + process.stderr.write(chunk); + captured += chunk; + if (captured.length > CAPTURED_STDOUT_LIMIT) { + captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT); + } + }); + } + child.once("error", fail); + child.once("close", (code) => { + settle({ + exitCode: code ?? 1, + ...outputMode === "capture" ? { stdout: captured } : {} + }); + }); + if (stdin !== void 0) { + child.stdin.once("error", fail); + try { + child.stdin.end(stdin); + } catch (error) { + fail(error instanceof Error ? error : new Error(String(error))); + } + } +}); +var authenticateHarness = async (commandSpec, adapter, timeoutMs = AUTHENTICATION_TIMEOUT_MS) => { + const executable = commandSpec.executable; + try { + const result = await runProcess( + executable, + adapter.authenticationArgv(), + commandSpec.cwd, + void 0, + "ignore", + timeoutMs + ); + if (result.timedOut === true) { + return { + ok: false, + detail: `${executable} authentication check timed out after ${timeoutMs} ms and was terminated.` + }; + } + return result.exitCode === 0 ? { ok: true } : { + ok: false, + detail: `${executable} authentication check failed: exited ${result.exitCode}.` + }; + } catch (error) { + const code = error.code; + return { + ok: false, + detail: `${executable} authentication check could not launch${code === void 0 ? "" : ` (${code})`}: ${errorMessage(error)}` + }; + } +}; +var dependencies = { + executableExists: executableResolves, + authenticate: authenticateHarness, + launch: (commandSpec, options) => runProcess( + commandSpec.executable, + commandSpec.argv, + commandSpec.cwd, + commandSpec.stdin, + options?.captureStdout === true ? "capture" : "inherit" + ) +}; +var errorMessage = (error) => error instanceof Error ? error.message : String(error); +var prepareLaunch = async (harness, input, active, guard) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + if (!adapter) { + return { + kind: "fallback", + reason: "adapter-unavailable", + detail: `No adapter is registered for ${harness}.` + }; + } + const blocked = guard?.(); + if (blocked) return blocked; + const executable = adapter.executable; + if (!active.executableExists(executable)) { + return { + kind: "fallback", + reason: "executable-unavailable", + detail: `${executable} is unavailable.` + }; + } + const commandSpec = adapter.buildCommand(input); + const authentication = await active.authenticate(commandSpec, adapter); + if (!authentication.ok) { + return { + kind: "fallback", + reason: "authentication-failed", + detail: authentication.detail ?? `${adapter.executable} authentication check failed.` + }; + } + return { kind: "ready", command: commandSpec }; +}; +var launchPrepared = async (prepared, active, label, captureStdout = false) => { + if (prepared.kind === "fallback") return prepared; + try { + const launched = await active.launch(prepared.command, { captureStdout }); + const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout }; + return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout }; + } catch (error) { + return { + kind: "infrastructure-failure", + detail: `External ${label} process failed: ${errorMessage(error)}` + }; + } +}; +var dispatchReview = async (request, overrides = {}) => { + const active = { ...dependencies, ...overrides }; + const prepared = await prepareLaunch(request.harness, reviewCommandRequest(request), active); + return launchPrepared(prepared, active, "review", true); +}; + +// src/skill-scripts/shared/harness-availability.ts +var AVAILABILITY_REGISTRY_VERSION = 4; +var AVAILABLE_TTL_MS = 30 * 60 * 1e3; +var UNAVAILABLE_TTL_MS = 5 * 60 * 1e3; +var PROBE_TIMEOUT_MS = 2e4; +var AVAILABILITY_CACHE_RELATIVE_PATH = path7.join("runtime", "harness-availability.json"); +var CACHE_VERSION = 2; +var availabilityDefinition = (harness) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + return { + executable: adapter.executable, + buildCommand: (cwd, cliArgs, prompt) => adapter.buildCommand({ cliArgs, workspace: cwd, prompt }) + }; +}; +var HARNESS_AVAILABILITY_REGISTRY = Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, availabilityDefinition(harness)]) + ) +); +var runProbe = (command2, timeoutMs) => new Promise((resolve4) => { + let stdout = ""; + let stderr = ""; + let settled = false; + let timedOut = false; + const finish = (result) => { + if (settled) return; + settled = true; + resolve4(result); + }; + const child = (0, import_child_process3.spawn)(command2.executable, command2.argv, { + cwd: command2.cwd, + shell: false, + stdio: ["pipe", "pipe", "pipe"] + }); + child.stdout?.setEncoding("utf8"); + child.stderr?.setEncoding("utf8"); + child.stdout?.on("data", (chunk) => { + stdout = (stdout + chunk).slice(-4096); + }); + child.stderr?.on("data", (chunk) => { + stderr = (stderr + chunk).slice(-4096); + }); + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGKILL"); + child.stdout?.destroy(); + child.stderr?.destroy(); + finish({ exitCode: 1, timedOut, stdout, stderr }); + }, timeoutMs); + child.once("error", (error) => { + clearTimeout(timer); + finish({ exitCode: 1, timedOut, stdout, stderr, error: error.message }); + }); + child.once("close", (code) => { + clearTimeout(timer); + finish({ exitCode: code ?? 1, timedOut, stdout, stderr }); + }); + child.stdin?.on("error", () => void 0); + child.stdin?.end(command2.stdin); +}); +var probeFailureReason = (probe) => { + const reason = probe.timedOut ? `Harness readiness check timed out after ${PROBE_TIMEOUT_MS} ms.` : probe.error ? `Harness readiness check could not launch: ${probe.error}` : probe.exitCode !== 0 ? `Harness readiness check exited ${probe.exitCode}.` : "Harness exited 0 but did not create the required readiness file with the expected content."; + const diagnostics = [ + probe.stderr?.trim() ? `stderr: ${probe.stderr.trim().slice(-4096)}` : "", + probe.stdout?.trim() ? `stdout: ${probe.stdout.trim().slice(-4096)}` : "" + ].filter(Boolean); + return [reason, ...diagnostics].join(" "); +}; +var defaultDependencies = { + now: Date.now, + resolveExecutable: resolveExecutablePath, + runProbe +}; +var isHarness = (value) => typeof value === "string" && SUPPORTED_HARNESSES.includes(value); +var isCacheEntry = (value) => { + if (!value || typeof value !== "object") return false; + const entry = value; + return typeof entry.key === "string" && isHarness(entry.harness) && typeof entry.available === "boolean" && typeof entry.observedAt === "number" && Number.isFinite(entry.observedAt) && typeof entry.expiresAt === "number" && Number.isFinite(entry.expiresAt) && typeof entry.reason === "string"; +}; +var emptyCache = () => ({ version: CACHE_VERSION, entries: [] }); +var readCache = (cachePath) => { + try { + const parsed = JSON.parse(fs6.readFileSync(cachePath, "utf8")); + if (!parsed || typeof parsed !== "object") return emptyCache(); + const record = parsed; + if (record.version !== CACHE_VERSION || !Array.isArray(record.entries)) return emptyCache(); + return { version: CACHE_VERSION, entries: record.entries.filter(isCacheEntry) }; + } catch { + return emptyCache(); + } +}; +var writeCache = (cachePath, entry) => { + fs6.mkdirSync(path7.dirname(cachePath), { recursive: true }); + const cache = readCache(cachePath); + const existingIndex = cache.entries.findIndex((candidate) => candidate.key === entry.key); + if (existingIndex === -1) cache.entries.push(entry); + else if (cache.entries[existingIndex].observedAt <= entry.observedAt) { + cache.entries[existingIndex] = entry; + } + const temporary = `${cachePath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.tmp`; + try { + fs6.writeFileSync(temporary, `${JSON.stringify(cache, null, 2)} +`, { mode: 384 }); + fs6.renameSync(temporary, cachePath); + } finally { + try { + fs6.unlinkSync(temporary); + } catch { + } + } +}; +var cacheKey = (harness, executableIdentity, invocation) => (0, import_crypto2.createHash)("sha256").update( + JSON.stringify({ + harness, + executableIdentity, + cliArgsHash: invocation.cliArgsHash, + normalizationVersion: HARNESS_CONFIGURATION_NORMALIZATION_VERSION, + probeRegistryVersion: AVAILABILITY_REGISTRY_VERSION + }) +).digest("hex"); +var readinessEvidence = () => { + const nonce = (0, import_crypto2.randomUUID)(); + return { + file: "strikethroo-readiness.txt", + content: `strikethroo-readiness:${nonce} +` + }; +}; +var readinessPrompt = (evidence) => `Run a shell command that creates ${evidence.file} in the current workspace with the exact UTF-8 content ${JSON.stringify(evidence.content)}. Do not use a file editing tool. +STRIKETHROO_READINESS=${JSON.stringify(evidence)} +`; +var initializeProbeWorkspace = () => { + const workspace = fs6.mkdtempSync(path7.join(os.tmpdir(), "strikethroo-harness-probe-")); + const initialized = (0, import_child_process3.spawnSync)("git", ["init", "--quiet"], { + cwd: workspace, + shell: false, + stdio: "ignore", + timeout: 5e3 + }); + if (initialized.status === 0 && !initialized.error) return workspace; + fs6.rmSync(workspace, { recursive: true, force: true }); + return void 0; +}; +var hasReadinessEvidence = (workspace, evidence) => { + const target = path7.join(workspace, evidence.file); + try { + return fs6.lstatSync(target).isFile() && fs6.readFileSync(target, "utf8") === evidence.content; + } catch { + return false; + } +}; +var outcome = (harness, available, now, reason) => ({ + harness, + available, + observedAt: now, + expiresAt: now + (available ? AVAILABLE_TTL_MS : UNAVAILABLE_TTL_MS), + reason, + source: "probe" +}); +var invocationFor = (request, harness) => { + if (request.invocation) return request.invocation; + const loaded = loadHarnessConfiguration(request.strikethrooRoot); + return loaded.kind === "config" ? loaded.config[harness] : void 0; +}; +var checkHarnessAvailability = async (request, overrides = {}) => { + const active = { ...defaultDependencies, ...overrides }; + const now = active.now(); + if (request.harness === void 0 || request.harness === request.currentHarness) { + return { + harness: request.harness ?? request.currentHarness, + available: true, + observedAt: now, + expiresAt: now, + reason: "Native/current harness targets do not require a probe.", + source: "bypass" + }; + } + const harness = request.harness; + const invocation = invocationFor(request, harness); + if (!invocation) return outcome(harness, false, now, "Harness configuration is invalid."); + const definition = HARNESS_AVAILABILITY_REGISTRY[harness]; + const executableIdentity = active.resolveExecutable(definition.executable); + if (!executableIdentity) + return outcome( + harness, + false, + now, + `Harness executable '${definition.executable}' was not found on PATH.` + ); + const key = cacheKey(harness, executableIdentity, invocation); + const cachePath = path7.join(request.strikethrooRoot, AVAILABILITY_CACHE_RELATIVE_PATH); + const cached = readCache(cachePath).entries.find( + (entry) => entry.key === key && entry.expiresAt > now + ); + if (cached) { + const { key: _key, ...cachedOutcome } = cached; + return { ...cachedOutcome, source: "cache" }; + } + const complete = (result) => { + const { source: _source, ...cacheEntry } = result; + try { + writeCache(cachePath, { key, ...cacheEntry }); + } catch { + } + return result; + }; + const probeWorkspace = initializeProbeWorkspace(); + if (!probeWorkspace) { + return complete( + outcome( + harness, + false, + now, + "Could not initialize the disposable Git workspace for the readiness check." + ) + ); + } + try { + const evidence = readinessEvidence(); + const command2 = definition.buildCommand( + probeWorkspace, + invocation.cliArgs, + readinessPrompt(evidence) + ); + const probe = await active.runProbe( + { ...command2, executable: executableIdentity }, + PROBE_TIMEOUT_MS + ); + const available = probe.exitCode === 0 && !probe.timedOut && hasReadinessEvidence(probeWorkspace, evidence); + return complete( + outcome( + harness, + available, + now, + available ? "Harness readiness verified." : probeFailureReason(probe) + ) + ); + } finally { + fs6.rmSync(probeWorkspace, { recursive: true, force: true }); + } +}; + +// src/skill-scripts/shared/harness-discovery.ts +var discoverHarnesses = async (request, overrides = {}) => { + const configuration = loadHarnessConfiguration(request.strikethrooRoot); + if (configuration.kind === "invalid") { + const now = (overrides.now ?? Date.now)(); + return { + outcomes: SUPPORTED_HARNESSES.map((harness) => ({ + harness, + available: harness === request.currentHarness, + observedAt: now, + expiresAt: now, + reason: harness === request.currentHarness ? "Native/current harness targets do not require a probe." : "Harness configuration is invalid.", + source: harness === request.currentHarness ? "bypass" : "probe" + })), + reviewerCandidates: [], + configurationErrors: configuration.errors + }; + } + const outcomes = await Promise.all( + SUPPORTED_HARNESSES.map(async (harness) => { + try { + return await checkHarnessAvailability( + { + strikethrooRoot: request.strikethrooRoot, + workspace: request.workspace, + harness, + currentHarness: request.currentHarness, + invocation: configuration.config[harness] + }, + overrides + ); + } catch (error) { + const now = Date.now(); + return { + harness, + available: false, + observedAt: now, + expiresAt: now, + reason: error instanceof Error ? error.message : "Harness availability check failed.", + source: "probe" + }; + } + }) + ); + const reviewerCandidates = SUPPORTED_HARNESSES.filter((harness) => { + if (harness === request.currentHarness) return false; + const outcome2 = outcomes.find((candidate) => candidate.harness === harness); + return outcome2?.available === true; + }); + const reviewerInvocations = Object.fromEntries( + reviewerCandidates.map((harness) => [harness, { cliArgs: configuration.config[harness].cliArgs }]) + ); + return { outcomes, reviewerCandidates, reviewerInvocations }; +}; + +// src/skill-scripts/shared/review-findings.ts +var import_child_process4 = require("child_process"); +var SEVERITIES = ["critical", "major", "minor", "info"]; +var CONFIDENCES = ["high", "medium", "low"]; +var XMLLINT_TIMEOUT_MS = 3e4; +var isSeverity = (value) => SEVERITIES.includes(value); +var isConfidence = (value) => CONFIDENCES.includes(value); +var OUTPUT_CAP = 2e3; +var runXmllint = (args, timeoutMs) => new Promise((resolve4) => { + let settled = false; + let stdout = ""; + let stderr = ""; + const finish = (run2) => { + if (settled) return; + settled = true; + resolve4(run2); + }; + const capped = (current, chunk) => current.length < OUTPUT_CAP ? current + String(chunk).slice(0, OUTPUT_CAP - current.length) : current; + const child = (0, import_child_process4.spawn)("xmllint", ["--nonet", ...args], { + shell: false, + stdio: ["ignore", "pipe", "pipe"] + }); + const timer = setTimeout(() => { + child.kill("SIGKILL"); + finish({ kind: "timed-out" }); + }, timeoutMs); + child.stdout?.on("data", (chunk) => { + stdout = capped(stdout, chunk); + }); + child.stderr?.on("data", (chunk) => { + stderr = capped(stderr, chunk); + }); + child.once("error", (error) => { + clearTimeout(timer); + finish({ + kind: "launch-failed", + code: error.code, + message: error.message + }); + }); + child.once("close", (code) => { + clearTimeout(timer); + finish({ kind: "exited", code, stdout, stderr }); + }); +}); +var validateAgainstSchema = async (xsdFile, xmlFile, timeoutMs = XMLLINT_TIMEOUT_MS) => { + const run2 = await runXmllint(["--schema", xsdFile, xmlFile, "--noout"], timeoutMs); + switch (run2.kind) { + case "timed-out": + return { + kind: "validator-unavailable", + detail: `xmllint did not return a verdict on ${xmlFile} within ${timeoutMs} ms, so the findings could not be validated.` + }; + case "launch-failed": + return { + kind: "validator-unavailable", + detail: run2.code === "ENOENT" ? "`xmllint` was not found on PATH. The review gate validates every emitted review.xml against the vendored schema and cannot certify findings without it. Install libxml2-utils (or your platform equivalent) and re-run." : `\`xmllint\` could not be run (${run2.code ?? "unknown error"}): ${run2.message}` + }; + case "exited": + return run2.code === 0 ? { kind: "valid" } : { + kind: "invalid", + detail: run2.stderr.trim() || `xmllint exited ${run2.code ?? "with no status"}.` + }; + } +}; +var COMMENT_COUNT_XPATH = "count(//*[local-name()='comment'])"; +var countCommentsWithXmllint = async (xmlFile, timeoutMs = XMLLINT_TIMEOUT_MS) => { + const run2 = await runXmllint(["--xpath", COMMENT_COUNT_XPATH, xmlFile], timeoutMs); + if (run2.kind !== "exited" || run2.code !== 0) return null; + const answer = run2.stdout.trim(); + return /^\d+(\.0+)?$/.test(answer) ? Number(answer) : null; +}; +var stripCommentsAndCdata = (xml) => { + let kept = ""; + let index = 0; + while (index < xml.length) { + const comment = xml.indexOf(""] : [""]; + const end = xml.indexOf(closer, next + opener.length); + index = end === -1 ? xml.length : end + closer.length; + } + return kept; +}; +var FORBIDDEN_DECLARATION_RE = / FORBIDDEN_DECLARATION_RE.test(stripCommentsAndCdata(xml)); +var SUMMARY_LIMIT = 400; +var decodeEntities = (text) => text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&#(\d+);/g, (_match, digits) => String.fromCodePoint(Number(digits))).replace( + /&#x([0-9a-fA-F]+);/g, + (_match, hex) => String.fromCodePoint(parseInt(hex, 16)) +).replace(/&/g, "&"); +var localName = (raw) => { + const colon = raw.indexOf(":"); + return colon === -1 ? raw : raw.slice(colon + 1); +}; +var ATTRIBUTE_RE = /([A-Za-z_:][-.\w:]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g; +var parseAttributes = (source) => { + const attributes = {}; + ATTRIBUTE_RE.lastIndex = 0; + let match = ATTRIBUTE_RE.exec(source); + while (match !== null) { + attributes[localName(match[1])] = decodeEntities(match[2] ?? match[3] ?? ""); + match = ATTRIBUTE_RE.exec(source); + } + return attributes; +}; +var findTagEnd = (xml, start) => { + let quote = null; + for (let index = start + 1; index < xml.length; index += 1) { + const character = xml[index]; + if (quote !== null) { + if (character === quote) quote = null; + continue; + } + if (character === '"' || character === "'") { + quote = character; + continue; + } + if (character === ">") return index + 1; + } + return xml.length; +}; +var lineRange = (attributes) => { + const newStart = attributes["new-line-start"]; + const newEnd = attributes["new-line-end"]; + if (newStart !== void 0) return `new:${newStart}-${newEnd ?? newStart}`; + const oldStart = attributes["old-line-start"]; + const oldEnd = attributes["old-line-end"]; + if (oldStart !== void 0) return `old:${oldStart}-${oldEnd ?? oldStart}`; + return null; +}; +var parseReviewFindings = (xml) => { + const findings = []; + let file = null; + let comment = null; + let capture = null; + let buffer = ""; + let index = 0; + const appendText = (text) => { + if (capture !== null) buffer += text; + }; + while (index < xml.length) { + const open = xml.indexOf("<", index); + if (open === -1) break; + if (open > index) appendText(decodeEntities(xml.slice(index, open))); + if (xml.startsWith("", open + 4); + index = end === -1 ? xml.length : end + 3; + continue; + } + if (xml.startsWith("", open + 9); + appendText(xml.slice(open + 9, end === -1 ? xml.length : end)); + index = end === -1 ? xml.length : end + 3; + continue; + } + if (xml.startsWith("", open + 2); + index = end === -1 ? xml.length : end + 2; + continue; + } + if (xml.startsWith("]+)/.exec(body); + if (nameMatch === null) continue; + const name = localName(nameMatch[1]); + const rest = body.slice(nameMatch[0].length); + if (closing) { + if (name === "body" && capture === "body") { + if (comment !== null) comment.summary = buffer.trim().slice(0, SUMMARY_LIMIT); + capture = null; + } else if (name === "category" && capture === "category") { + if (comment !== null) comment.category = buffer.trim() || null; + capture = null; + } else if (name === "comment") { + if (comment !== null) findings.push({ ...comment }); + comment = null; + capture = null; + } else if (name === "file") { + file = null; + } + continue; + } + const attributes = parseAttributes(rest); + if (name === "file") { + if (!selfClosing) file = attributes["path"] ?? ""; + continue; + } + if (name === "comment") { + const severity = attributes["severity"] ?? ""; + const confidence = attributes["confidence"] ?? ""; + comment = { + file: file ?? "", + location: lineRange(attributes), + // Absent, empty, and unrecognised all become null. The label is + // advisory, so an unreadable one is dropped rather than guessed at. + severity: isSeverity(severity) ? severity : null, + confidence: isConfidence(confidence) ? confidence : null, + category: null, + summary: "" + }; + capture = null; + if (selfClosing) { + findings.push({ ...comment }); + comment = null; + } + continue; + } + if (comment === null) continue; + if (name === "body") { + capture = "body"; + buffer = ""; + } else if (name === "category") { + capture = "category"; + buffer = ""; + } + } + return findings; +}; +var countFindings = (findings) => { + const counts = { + total: findings.length, + critical: 0, + major: 0, + minor: 0, + info: 0, + unlabelled: 0 + }; + for (const finding of findings) { + if (finding.severity === null) counts.unlabelled += 1; + else counts[finding.severity] += 1; + } + return counts; +}; + +// src/skill-scripts/code-review.ts +var HOOK_RELATIVE_PATH = path8.join("config", "hooks", "CODE_REVIEW.md"); +var XSD_RELATIVE_PATH = path8.join("config", "schemas", "self-review-v2.xsd"); +var REVIEW_DIR_NAME = "review"; +var BASE_COMMIT_FILE_NAME = "base-commit.json"; +var REVIEW_FILE_NAME = "review.xml"; +var FINDINGS_FILE_NAME = "findings.json"; +var TRANSCRIPT_FILE_NAME = "reviewer-output.txt"; +var SHA_RE = /^[0-9a-f]{40}$/i; +var errorMessage2 = (error) => error instanceof Error ? error.message : String(error); +var readFileOrNull = (filePath) => { + try { + return fs7.readFileSync(filePath, "utf8"); + } catch { + return null; + } +}; +var writeTranscript = (reviewDir, transcript) => { + if (transcript === void 0 || transcript === "") return; + try { + fs7.mkdirSync(reviewDir, { recursive: true }); + fs7.writeFileSync(path8.join(reviewDir, TRANSCRIPT_FILE_NAME), transcript, "utf8"); + } catch { + } +}; +var createFindingsGate = (options = {}) => async (context) => { + const countComments = options.countComments ?? countCommentsWithXmllint; + const reviewDir = path8.dirname(context.reviewFile); + const findingsFile = path8.join(reviewDir, FINDINGS_FILE_NAME); + const record = (payload) => { + try { + fs7.mkdirSync(reviewDir, { recursive: true }); + fs7.writeFileSync(findingsFile, `${JSON.stringify(payload, null, 2)} +`, "utf8"); + } catch (error) { + throw new Error( + `The review findings could not be written to ${findingsFile}: ${errorMessage2(error)}` + ); + } + }; + const base = { reviewFile: context.reviewFile, xsdFile: context.xsdFile }; + const delivered = _extractReviewDocument(context.reviewerStdout, context.deliveryToken); + if (delivered === null) { + const detail = "The reviewer printed no complete findings document between this dispatch's delimiters. A review with no findings document cannot be read as a review with no findings."; + record({ ...base, status: "findings-absent", detail, findings: [] }); + return { kind: "findings-absent", detail }; + } + try { + fs7.mkdirSync(reviewDir, { recursive: true }); + fs7.writeFileSync( + context.reviewFile, + delivered.endsWith("\n") ? delivered : `${delivered} +`, + "utf8" + ); + } catch (error) { + throw new Error( + `The delivered findings document could not be written to ${context.reviewFile}: ` + errorMessage2(error) + ); + } + if (hasForbiddenDeclarations(delivered)) { + const detail = `${context.reviewFile} carries a DOCTYPE or entity declaration ( elements, so the ${findings.length} finding(s) the scanner read could not be certified and none was recorded.`; + record({ ...base, status: "validator-unavailable", detail, findings: [] }); + return { kind: "validator-unavailable", detail }; + } + if (independent !== findings.length) { + const detail = `${context.reviewFile} validated, but the scanner read ${findings.length} finding(s) where xmllint counted ${independent} element(s). A count that disagrees with the validated document cannot be certified, so none of the findings was recorded.`; + record({ ...base, status: "findings-absent", detail, findings: [] }); + return { kind: "findings-absent", detail }; + } + const counts = countFindings(findings); + record({ ...base, status: "evaluated", counts, findings }); + return { kind: "evaluated", counts, findingsFile }; +}; +var CONTINUE = { action: "continue", exitCode: 0 }; +var HALT_REVIEW = { action: "halt", exitCode: 1 }; +var HALT_INFRASTRUCTURE = { action: "halt", exitCode: 2 }; +var _classify = (outcome2) => { + switch (outcome2.kind) { + case "infrastructure-failure": + return HALT_INFRASTRUCTURE; + case "launched-failure": + return HALT_REVIEW; + case "reviewed": + return outcome2.verdict.kind === "review-recorded" ? CONTINUE : HALT_REVIEW; + case "skipped": + case "fallback": + return CONTINUE; + } +}; +var reviewSummary = (outcome2) => { + const reviewer = "harness" in outcome2 ? `Harness: ${outcome2.harness}; model: CLI-selected (exact model unknown).` : "No reviewer performed a certified review."; + if (outcome2.kind === "reviewed" && outcome2.verdict.kind === "review-recorded" && "counts" in outcome2) { + return `${outcome2.counts.total === 0 ? "Pass" : "Address"}; ${reviewer} Findings: ${outcome2.counts.total}.`; + } + return `Failed; ${reviewer} ${outcome2.detail}`.replace(/\s+/g, " ").trim(); +}; +var decide = (outcome2) => ({ + ...outcome2, + action: _classify(outcome2).action, + codeReview: reviewSummary(outcome2) +}); +var _readBaseCommit = (filePath) => { + const raw = readFileOrNull(filePath); + if (raw === null) return null; + try { + const parsed = JSON.parse(raw); + if (parsed && typeof parsed === "object") { + const candidate = parsed.baseCommit; + if (typeof candidate === "string" && SHA_RE.test(candidate)) return candidate; + } + } catch { + return null; + } + return null; +}; +var GENERATED_ATTRIBUTES = ["linguist-generated", "linguist-vendored"]; +var ATTRIBUTE_UNMARKED = /* @__PURE__ */ new Set(["unspecified", "unset", "false"]); +var attributeExcluded = (workspace, files) => { + const excluded = /* @__PURE__ */ new Set(); + if (files.length === 0) return excluded; + const report = execGit( + ["-C", workspace, "check-attr", "--stdin", "-z", ...GENERATED_ATTRIBUTES], + { input: files.map((file) => `${file}\0`).join(""), trim: false } + ); + if (report === null) return null; + const fields = report.split("\0"); + for (let i = 0; i + 2 < fields.length; i += 3) { + if (!ATTRIBUTE_UNMARKED.has(fields[i + 2])) excluded.add(fields[i]); + } + return excluded; +}; +var excludedPaths = (workspace, baseCommit) => { + const changed = execGit( + ["-C", workspace, "diff", "--no-renames", "--name-only", "-z", baseCommit, "--"], + { trim: false } + ); + if (changed === null) return null; + const excluded = attributeExcluded(workspace, splitNulDelimited(changed)); + return excluded === null ? null : [...excluded]; +}; +var untrackedPaths = (workspace) => { + const listed = execGit( + [ + "-c", + "core.quotePath=false", + "-C", + workspace, + "ls-files", + "--others", + "--exclude-standard", + "-z" + ], + { trim: false } + ); + if (listed === null) return null; + const files = splitNulDelimited(listed); + const excluded = attributeExcluded(workspace, files); + if (excluded === null) return null; + return files.filter((file) => !excluded.has(file)); +}; +var untrackedDiff = (workspace, file) => execGitDiffAllowingChanges([ + "-C", + workspace, + "diff", + "--no-index", + "--src-prefix=a/", + "--dst-prefix=b/", + "--", + "/dev/null", + file +]); +var _readCumulativeDiff = (workspace, baseCommit) => { + const excluded = excludedPaths(workspace, baseCommit); + if (excluded === null) return null; + const tracked = execGit([ + "-C", + workspace, + "diff", + baseCommit, + "--", + ".", + ...excluded.map((file) => `:(exclude,literal)${file}`) + ]); + if (tracked === null) return null; + const untracked = untrackedPaths(workspace); + if (untracked === null) return null; + const added = []; + for (const file of untracked) { + const diff = untrackedDiff(workspace, file); + if (diff === null) return null; + if (diff.trim() !== "") added.push(diff); + } + return [tracked, ...added].filter((part) => part.trim() !== "").join("\n"); +}; +var defaultDependencies2 = { + discover: discoverHarnesses, + dispatch: dispatchReview, + readDiff: _readCumulativeDiff, + validatorAvailable: () => executableResolves("xmllint") +}; +var readReviewerSkill = () => { + const skillFile = path8.resolve(__dirname, "..", "SKILL.md"); + const content = readFileOrNull(skillFile); + return content === null ? "Load the `st-code-review` skill and follow its Operating Procedure. If that skill is not installed on this harness, follow the mandate below exactly." : content; +}; +var _makeDeliveryToken = () => crypto.randomBytes(6).toString("hex"); +var beginMarker = (token) => `<<>>`; +var endMarker = (token) => `<<>>`; +var ANSI_PATTERN = /\u001b\[[0-9;?]*[ -/]*[@-~]/g; +var _extractReviewDocument = (stdout, token) => { + const clean = stdout.replace(ANSI_PATTERN, ""); + const begin = beginMarker(token); + const end = endMarker(token); + let searchFrom = clean.length; + while (searchFrom >= 0) { + const endIndex = clean.lastIndexOf(end, searchFrom); + if (endIndex === -1) return null; + const beginIndex = clean.lastIndexOf(begin, endIndex); + if (beginIndex === -1) return null; + const inner = clean.slice(beginIndex + begin.length, endIndex).trim(); + if (inner.startsWith(" [ + `Strikethroo code review gate \u2014 Plan ${input.planId}.`, + "", + "You are the independent reviewer, running on a different harness than the one", + "that wrote this code. You detect; you never fix. Do not edit, create, or delete", + "source files. Do not run formatters. Do not commit. Your entire output is one", + "findings document, printed as described below, plus a short report of the counts.", + "", + `Repository / workspace root: ${input.workspace}`, + `Strikethroo workspace root: ${input.strikethrooRoot}`, + `Plan document (read it in full): ${input.planFile}`, + `Review mandate hook: ${input.hookFile}`, + `Findings schema to validate against: ${input.xsdFile}`, + `Base commit anchoring this plan's scope: ${input.baseCommit}`, + "", + "## How to deliver your findings", + "", + "Print the complete findings document as the final thing you print, between these", + "exact lines:", + "", + beginMarker(input.deliveryToken), + // Must not begin with ` with no children and report\nzero findings. That is not an error." : ` +<<>> +${input.diff} +<<>>`, + "" +].join("\n"); +var skip = (reason, detail) => decide({ kind: "skipped", reason, detail }); +var resolveReviewContext = (startPath, validatorAvailable = () => executableResolves("xmllint")) => { + const strikethrooRoot = findStrikethrooRoot(startPath); + if (!strikethrooRoot) { + return { + kind: "ended", + result: decide({ + kind: "infrastructure-failure", + detail: `No Strikethroo workspace was found from ${startPath}.` + }) + }; + } + const hookFile = path8.join(strikethrooRoot, HOOK_RELATIVE_PATH); + const hookContent = readFileOrNull(hookFile); + if (hookContent === null) { + return { + kind: "ended", + result: skip( + "hook-absent", + `No code review mandate at ${hookFile}, so the review gate was skipped. Re-run \`npx strikethroo init\` to add it.` + ) + }; + } + if (hookContent.trim().length === 0) { + return { + kind: "ended", + result: skip( + "hook-empty", + `The code review mandate at ${hookFile} is empty, which is the documented way to disable the gate, so the review gate was skipped.` + ) + }; + } + const xsdFile = path8.join(strikethrooRoot, XSD_RELATIVE_PATH); + if (!fs7.existsSync(xsdFile)) { + return { + kind: "ended", + result: skip( + "xsd-absent", + `No findings schema at ${xsdFile}, so findings could not be validated and the review gate was skipped. Re-run \`npx strikethroo init\` to add it.` + ) + }; + } + if (!validatorAvailable()) { + return { + kind: "ended", + result: skip( + "validator-absent", + "No `xmllint` on PATH, so emitted findings could not be validated against the vendored schema and the review gate was skipped. Install libxml2-utils (Debian/Ubuntu), libxml2 (Homebrew), or your platform equivalent to enable the gate." + ) + }; + } + return { + kind: "resolved", + context: { + strikethrooRoot, + workspace: path8.dirname(path8.dirname(strikethrooRoot)), + hookFile, + hookContent, + xsdFile + } + }; +}; +var runReview = async (request, overrides = {}) => { + const dependencies2 = { ...defaultDependencies2, ...overrides }; + const startPath = request.startPath ?? process.cwd(); + const resolution = resolveReviewContext(startPath, dependencies2.validatorAvailable); + if (resolution.kind === "ended") return resolution.result; + const { strikethrooRoot, workspace, hookFile, hookContent, xsdFile } = resolution.context; + const resolved = resolvePlan(request.plan, startPath); + if (!resolved) { + return decide({ + kind: "infrastructure-failure", + detail: `Plan "${request.plan}" was not found or is invalid.` + }); + } + const { planDir, planFile, planId } = resolved; + const baseCommitFile = path8.join(planDir, REVIEW_DIR_NAME, BASE_COMMIT_FILE_NAME); + const baseCommit = _readBaseCommit(baseCommitFile); + if (baseCommit === null) { + return skip( + "base-commit-absent", + `No base commit was recorded at ${baseCommitFile}, so the review had no anchored diff scope and the review gate was skipped.` + ); + } + const discovery = await dependencies2.discover({ + strikethrooRoot, + workspace, + currentHarness: request.currentHarness + }); + if (discovery.configurationErrors !== void 0) { + return decide({ + kind: "infrastructure-failure", + detail: `Harness invocation configuration is invalid: ${discovery.configurationErrors.join( + " " + )}` + }); + } + const harness = discovery.reviewerCandidates[0]; + if (harness === void 0) { + return skip( + "no-reviewer-candidate", + `No reviewer candidate; review gate skipped. ${request.currentHarness} is excluded as the current harness. ` + SUPPORTED_HARNESSES.filter((candidate) => candidate !== request.currentHarness).map((candidate) => { + const outcome2 = discovery.outcomes.find((item) => item.harness === candidate); + return `${candidate}: ${outcome2?.reason ?? "No availability outcome was reported."}` + (outcome2?.source === "cache" ? " (cached readiness result)" : ""); + }).join(" ") + ); + } + const diff = dependencies2.readDiff(workspace, baseCommit); + if (diff === null) { + return decide({ + kind: "infrastructure-failure", + detail: `git diff ${baseCommit} failed in ${workspace}. The base commit was recorded, so this is a real failure rather than an absent-scope skip.` + }); + } + if (diff.trim() === "") { + return skip( + "empty-diff", + `The diff from ${baseCommit} to the working tree in ${workspace} is empty, so there was nothing to review. No reviewer was dispatched, and nothing was certified.` + ); + } + const reviewDir = path8.join(planDir, REVIEW_DIR_NAME); + const reviewFile = path8.join(reviewDir, REVIEW_FILE_NAME); + try { + fs7.mkdirSync(reviewDir, { recursive: true }); + } catch (error) { + return decide({ + kind: "infrastructure-failure", + detail: `Could not create the review directory ${reviewDir}: ${errorMessage2(error)}` + }); + } + const staleArtifacts = [reviewFile, path8.join(reviewDir, TRANSCRIPT_FILE_NAME)]; + for (const stale of staleArtifacts) { + try { + fs7.rmSync(stale, { force: true }); + } catch (error) { + return decide({ + kind: "infrastructure-failure", + detail: `Could not remove the stale review artifact ${stale}: ${errorMessage2(error)}` + }); + } + } + const deliveryToken = _makeDeliveryToken(); + const prompt = buildReviewerPrompt({ + planId, + planFile, + strikethrooRoot, + workspace, + hookFile, + hookContent, + xsdFile, + baseCommit, + diff, + skillInstructions: readReviewerSkill(), + deliveryToken + }); + const invocation = discovery.reviewerInvocations?.[harness]; + const dispatched = await dependencies2.dispatch({ + harness, + workspace, + prompt, + ...invocation === void 0 ? {} : { + cliArgs: invocation.cliArgs + } + }); + if (dispatched.kind === "infrastructure-failure") { + return decide({ kind: "infrastructure-failure", detail: dispatched.detail }); + } + if (dispatched.kind === "fallback") { + return decide({ + kind: "fallback", + harness, + reason: dispatched.reason, + detail: dispatched.detail + }); + } + if (dispatched.kind === "launched-failure") { + writeTranscript(reviewDir, dispatched.stdout); + return decide({ + kind: "launched-failure", + harness, + reviewFile, + exitCode: dispatched.exitCode, + detail: `The ${harness} reviewer exited ${dispatched.exitCode}.` + }); + } + const evaluate = dependencies2.evaluateFindings ?? createFindingsGate(); + const findingsGate = await evaluate({ + reviewFile, + xsdFile, + planDir, + reviewerStdout: dispatched.stdout ?? "", + deliveryToken + }); + if (findingsGate.kind !== "evaluated") { + writeTranscript(reviewDir, dispatched.stdout); + } + return decide({ + kind: "reviewed", + harness, + baseCommit, + reviewFile, + ...reviewedFieldsFor(findingsGate) + }); +}; +var reviewedFieldsFor = (outcome2) => { + if (outcome2.kind !== "evaluated") { + return { verdict: { kind: "review-failed" }, detail: outcome2.detail }; + } + const { counts, findingsFile } = outcome2; + if (counts.total === 0) { + return { + verdict: { kind: "review-recorded" }, + counts, + detail: `The reviewer raised no findings. See ${findingsFile}.` + }; + } + const byLabel = SEVERITIES.filter((label) => counts[label] > 0).map((label) => `${counts[label]} ${label}`).concat(counts.unlabelled > 0 ? [`${counts.unlabelled} unlabelled`] : []).join(", "); + return { + verdict: { kind: "review-recorded" }, + counts, + detail: `The reviewer raised ${counts.total} finding(s) (${byLabel}). They are recorded, not applied: read them and decide which to act on. See ${findingsFile}.` + }; +}; +var _resultLine = (result) => `${JSON.stringify(result)} +`; +var emit = (result) => { + process.stdout.write(_resultLine(result)); + process.exit(_classify(result).exitCode); +}; +var main = async (startPath = process.cwd()) => { + const [planArg, harnessArg] = process.argv.slice(2); + if (!planArg || !harnessArg || !SUPPORTED_HARNESSES.includes(harnessArg)) { + emit( + decide({ + kind: "infrastructure-failure", + detail: `Usage: code-review.cjs . is one of: ${SUPPORTED_HARNESSES.join(", ")}.` + }) + ); + } + const result = await runReview({ + plan: planArg, + currentHarness: harnessArg, + startPath + }); + emit(result); +}; +if (require.main === module) { + main().catch((error) => { + emit( + decide({ + kind: "infrastructure-failure", + detail: `Code review gate infrastructure failed: ${errorMessage2(error)}` + }) + ); + }); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _classify, + _extractReviewDocument, + _makeDeliveryToken, + _readBaseCommit, + _readCumulativeDiff, + _resultLine, + buildReviewerPrompt, + createFindingsGate, + main, + runReview +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-code-review/scripts/find-strikethroo-root.cjs b/.agents/skills/st-code-review/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-code-review/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-code-review/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-code-review/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-code-review/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-create-plan/SKILL.md b/.agents/skills/st-create-plan/SKILL.md new file mode 100644 index 0000000..723fd6d --- /dev/null +++ b/.agents/skills/st-create-plan/SKILL.md @@ -0,0 +1,111 @@ +--- +name: st-create-plan +description: Use when the user asks to draft, scope, or write up a new Strikethroo plan for a work order, feature, or initiative in this repository — triggers include create plan, new plan, plan this, scope a plan, strikethroo plan. Do not use to decompose an existing plan into tasks, to execute a plan, or for generic brainstorming outside Strikethroo. +--- + +# st-create-plan + +## Inputs + +The user's request supplies the work order. + +## Operating Procedure + +### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +### 2. Load project context + +Read `/config/STRIKETHROO.md` for this project's directory conventions. +Read `/config/hooks/PRE_PLAN.md` and execute its instructions before +proceeding. Read `/config/templates/PLAN_TEMPLATE.md`; the plan must +conform to it. + +Also read `/config/shared/clarification-gate.md` and +`/config/shared/anti-rationalization.md`. + +### 3. Analyze the work order + +Identify: + +- Objective. +- Scope and explicit boundaries. +- Success criteria. +- Dependencies, prerequisites, blockers. +- Technical requirements and constraints. + +### 4. Clarification loop + +If any critical context is missing, ask the user targeted questions. Keep +looping until you have no further questions. Explicitly confirm whether +backwards compatibility is required. Never invent answers; never paper over +a missing answer. + +If the user declines to clarify a blocking question, stop and report the +plan as needing clarification. Do not produce a partial plan. + +Follow the clarification cadence in `/config/shared/clarification-gate.md`. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "I can reasonably assume the answer." | An assumption is not an answer. Ask the question; never invent answers. | +| "Asking again is annoying." | A question the user can decline is recoverable; a silent wrong assumption is not. Ask. | +| "The user implied it, so it's settled." | An implication is not a confirmation. Surface it as a question and get an explicit answer. | + +### 5. Allocate the next plan ID + +Run `scripts/get-next-plan-id.cjs` for the next available plan ID. Compute its +zero-padded form for the directory name (`{padded-id}--{slug}`) and use the +unpadded integer in the plan frontmatter. + +### 6. Emit the plan + +Write the plan to +`/plans/{padded-id}--{slug}/plan-{padded-id}--{slug}.md`, conforming to +`/config/templates/PLAN_TEMPLATE.md` in both frontmatter and sections. +Include no time estimates, task lists, or code samples; those belong to the +task-generation step. + +Derive `` from the plan summary: lowercase, alphanumeric and hyphens +only, collapsed, trimmed. + +### 7. Run post-plan hook + +Execute `/config/hooks/POST_PLAN.md`. + +### 8. Emit the structured summary + +Conclude with exactly this block (a retained update notice, when present, follows separately): + +``` +--- + +Plan Summary: +- Plan ID: [numeric-id] +- Plan File: [absolute-path-to-plan-file] +``` + +The summary is consumed by downstream automation; keep the format exact. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. + +## Failure Modes + +- **Plan directory already exists for the allocated ID.** Re-run the + next-plan-id script and retry once. If the conflict persists, stop and + report. diff --git a/.agents/skills/st-create-plan/scripts/check-for-updates.cjs b/.agents/skills/st-create-plan/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-create-plan/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-create-plan/scripts/find-strikethroo-root.cjs b/.agents/skills/st-create-plan/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-create-plan/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-create-plan/scripts/get-next-plan-id.cjs b/.agents/skills/st-create-plan/scripts/get-next-plan-id.cjs new file mode 100644 index 0000000..b748d52 --- /dev/null +++ b/.agents/skills/st-create-plan/scripts/get-next-plan-id.cjs @@ -0,0 +1,199 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/get-next-plan-id.ts +var get_next_plan_id_exports = {}; +__export(get_next_plan_id_exports, { + main: () => main +}); +module.exports = __toCommonJS(get_next_plan_id_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; +var computeNextPlanId = (taskManagerRoot) => { + const plans = getAllPlans(taskManagerRoot); + return plans.reduce((max, p) => Math.max(max, p.id), 0) + 1; +}; + +// src/skill-scripts/get-next-plan-id.ts +var main = () => { + const rootArg = process.argv[2]; + let root; + if (rootArg) { + root = rootArg; + } else { + root = findStrikethrooRoot(process.cwd()); + } + if (!root) { + process.stderr.write( + "No .ai/strikethroo root found. Run this from inside an initialized strikethroo workspace.\n" + ); + process.exit(1); + } + process.stdout.write(`${computeNextPlanId(root)} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-execute-blueprint/SKILL.md b/.agents/skills/st-execute-blueprint/SKILL.md new file mode 100644 index 0000000..7c8bde3 --- /dev/null +++ b/.agents/skills/st-execute-blueprint/SKILL.md @@ -0,0 +1,198 @@ +--- +name: st-execute-blueprint +description: Use when the user asks to run, execute, implement, or carry out a Strikethroo plan or its blueprint by plan ID in this repository — triggers include execute blueprint, run the plan, implement plan, build the plan. Do not use to create a plan, to only generate tasks, to run a single task, or for generic development outside Strikethroo. +--- + +# st-execute-blueprint + +## Inputs + +The user supplies the numeric plan ID conversationally. + +## Operating Procedure + +### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +### 2. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, stop and ask the user to confirm the plan ID. +Do not guess a different ID. + +Run `scripts/validate-plan-blueprint.cjs planDir` and treat the +printed path as ``. + +### 3. Validate tasks and blueprint existence + +Run `scripts/validate-plan-blueprint.cjs taskCount` and +`scripts/validate-plan-blueprint.cjs blueprintExists`. + +### 4. Auto-generate tasks and blueprint if missing + +If `taskCount` is 0 or `blueprintExists` is `no`: + +Notify the user: "Tasks or execution blueprint not found. Generating tasks automatically..." + +- Follow the `st-generate-tasks` skill for this plan ID. Execute its operating procedure in full, including running `POST_TASK_GENERATION_ALL.md` to write the Execution Blueprint. +- Re-run the `planFile`, `planDir`, `taskCount`, and `blueprintExists` queries to refresh the resolved paths and counts. + +If the plan still has no tasks or no blueprint, stop and report failure. + +### 5. Optionally create a feature branch + +Run `scripts/create-feature-branch.cjs ` once before phase execution. A skip is not a failure. Continue on the current branch, and never create the branch by hand. Uncommitted or untracked changes are permitted only inside the repository-root `.ai/strikethroo` subtree. An error result halts execution; report it. + +Then run `scripts/capture-base-commit.cjs ` once to record the commit the review gate diffs against. A `skipped` result continues execution and means the review gate will skip. Only an `error` result halts. + +### 6. Load project context and execution blueprint + +Read these files, in order: + +- `/config/STRIKETHROO.md` +- The plan document at the path from step 2, including its Execution Blueprint section, which defines the phase groupings and task dispatch order. +- `/config/shared/verification-gate.md` and `/config/shared/anti-rationalization.md`, both applied in the phase loop below. + +### 7. Execute phases in order + +Use an internal task or todo tracker to monitor progress. For each phase defined in the Execution Blueprint: + +#### 7a. Phase pre-execution +Run `scripts/check-phase-readiness.cjs `. If the script exits non-zero, halt the phase and report the blocking issues before continuing. + +Read `/config/hooks/PRE_PHASE.md` and execute its instructions before starting the phase. + +#### 7b. Task dispatch +Identify all tasks scheduled for this phase whose dependencies are fully satisfied. Read `/config/hooks/PRE_TASK_ASSIGNMENT.md` and follow its instructions for agent selection before dispatching tasks. + +Resolve every selected task's execution route first. Invoke one resolver per selected +task simultaneously in a single parallel tool operation: + +```text +scripts/dispatch-task-execution.cjs resolve +``` + +Resolvers never launch external processes. After interpreting all route results, issue +every external execution and every sub-agent **together in one parallel +tool operation**. External execution uses: + +```text +scripts/dispatch-task-execution.cjs execute +``` + +`` is the exact supported harness identifier running this +skill; `` is the project working directory. + +Interpret the one-line JSON result and act on its `kind` exactly once: + +| `kind` | Required action | +| --- | --- | +| `native-default` | Dispatch natively with no execution-setting prose. | +| `native-override` | Dispatch natively, explicitly requiring the exact returned `model`. Require the returned `reasoningEffort` only when that property is present. | +| `external-override` | Run the `execute` command with the returned `handoff`, then read its result against this same table. | +| `fallback` | Nothing launched. Record the returned `reason` and `detail` visibly, then dispatch natively with no execution-setting prose. | +| `launched-success` | The external process exited zero. Do not dispatch natively; review status and evidence as you would for a native agent. | +| `launched-failure` | A failed task. Set its status to `failed` and run `/config/hooks/POST_ERROR_DETECTION.md`. Never retry it natively. | +| `infrastructure-failure` | Handle exactly as the preceding row. | + +Handoff rules: + +- Pass the exact opaque `handoff` string the resolver returned for that task. Never reconstruct one. +- Never reuse a handoff for another task, and never rerun resolution after launches begin. + +Deploy all remaining native sub-agents simultaneously. Each sub-agent must read and execute `/config/hooks/PRE_TASK_EXECUTION.md` before any implementation work, then execute the task and update its status. Do not run `scripts/check-for-updates.cjs`; delegated workers do not consume update notices. + +#### 7c. Phase completion verification +Ensure every task in the phase has status `completed` and collect its outputs. Do not accept a subagent's report of success as proof. Apply the evidence gate in `/config/shared/verification-gate.md` before marking the phase complete. + +#### 7d. Phase post-execution +Read `/config/hooks/POST_PHASE.md` and execute its instructions. Do not proceed to the next phase until this hook succeeds. + +Update the phase status to `completed` in the plan's Execution Blueprint section. + +Repeat for the next phase until all phases are complete. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "The subagent reported success, so the task is done." | A report is a claim, not evidence. Apply the verification gate before marking the phase complete. | +| "The tests probably pass." | "Probably" is a red flag. Run the proving command, read its output and exit code, then state the result. | +| "I'll verify later, after the next phase." | A phase is not complete until `POST_PHASE.md` succeeds against verified evidence. Verify now; do not advance on an unverified phase. | + +### 8. Post-execution validation + +Read `/config/hooks/POST_EXECUTION.md` and execute its instructions. If validation fails, halt execution. The plan remains in `plans/` for debugging. + +Before declaring execution complete, apply the evidence gate in `/config/shared/verification-gate.md` to the plan's Success Criteria and Self Validation steps. + +#### Run the code review gate + +After `POST_EXECUTION.md` reports green, follow the `st-code-review` skill and run its bundled mechanism: + +```text +code-review.cjs +``` + +Resolve `code-review.cjs` from the `st-code-review` skill's sibling `scripts` directory and pass the exact supported harness identifier running this skill. If the `st-code-review` skill is not installed, record that outcome in the execution summary and continue to summary and archival. + +Handle the one JSON line it prints on stdout, in this order: + +1. Copy it verbatim into the execution summary's review outcome. Do not reformat it or omit fields. +2. Follow its top-level `action`. If it is `halt`, stop, report the top-level `detail`, and emit the terminal Execution Summary with the review result. If it is `continue`, proceed to the execution summary and archival. +3. Only when `verdict.kind` is `review-recorded`, read `/review/review.xml` and `/review/findings.json`, then decide which findings to act on. `severity` and `confidence` are advisory labels, not instructions. + +Never report an uncertified review as clean. + +Hard rules: + +- The review runs once. Do not re-run the gate to check a fix. +- Detection uses the reviewer route. Dispatch each fix on the implementer route; the reviewer does not fix its findings. +- After any fix, re-run `POST_EXECUTION.md` in full before declaring execution complete. The earlier green result no longer applies. + +### 9. Append execution summary + +Append an execution summary section to the plan document, filling every field of `/config/templates/EXECUTION_SUMMARY_TEMPLATE.md`. Include a Code Review entry using the result’s `codeReview` field, or Failed with the reason no result was produced. Under Noteworthy Events, always record the review gate's JSON line verbatim, then which findings you acted on versus ignored and why. + +### 10. Archive the plan + +Move the completed plan directory from `/plans/` to `/archive/`, preserving the entire folder structure. If the move fails, log the error but do not fail the overall execution. + +## Failure Modes + +- **Execution errors.** If a task fails, read `/config/hooks/POST_ERROR_DETECTION.md`, document the error in Noteworthy Events, halt the phase, and request user direction before continuing. + +## Execution Summary + +Conclude with exactly this block (a retained update notice, when present, follows separately): + +``` +--- +Execution Summary: +- Plan ID: [numeric-id] +- Status: [Archived or Halted] +- Location: [absolute path to current plan directory] +- Code Review: [codeReview from the review result, or Failed with the reason no result was produced] +--- +``` + +Emit this block even when the review gate halts execution. Use the actual status and location; never claim archival after a halt. Copy `codeReview` without dropping the harness, model information, or rejection reasons. Findings acted on do not turn Address into Pass because the review is not re-run. If execution stops before review, report Failed with "Review was not run" and the blocking reason. + +The summary is consumed by downstream automation; keep the format exact. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. diff --git a/.agents/skills/st-execute-blueprint/scripts/capture-base-commit.cjs b/.agents/skills/st-execute-blueprint/scripts/capture-base-commit.cjs new file mode 100644 index 0000000..ee434e5 --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/capture-base-commit.cjs @@ -0,0 +1,342 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/capture-base-commit.ts +var capture_base_commit_exports = {}; +__export(capture_base_commit_exports, { + _isGitRepo: () => _isGitRepo, + _isValidSha: () => _isValidSha, + _readExistingBaseCommit: () => _readExistingBaseCommit, + main: () => main +}); +module.exports = __toCommonJS(capture_base_commit_exports); +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/git-utils.ts +var import_child_process = require("child_process"); +var GIT_OUTPUT_LIMIT = 64 * 1024 * 1024; +var run = (args, opts) => (0, import_child_process.execFileSync)("git", [...args], { + cwd: opts.cwd, + input: opts.input, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: GIT_OUTPUT_LIMIT +}); +var execGit = (args, opts = {}) => { + try { + const out = run(args, opts); + return opts.trim === false ? out : out.trim(); + } catch { + return null; + } +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/capture-base-commit.ts +var SHA_RE = /^[0-9a-f]{40}$/i; +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var _isGitRepo = () => execGit(["rev-parse", "--is-inside-work-tree"]) === "true"; +var _isValidSha = (value) => typeof value === "string" && SHA_RE.test(value); +var _readExistingBaseCommit = (filePath) => { + let raw; + try { + raw = fs4.readFileSync(filePath, "utf8"); + } catch { + return null; + } + try { + const parsed = JSON.parse(raw); + if (parsed && typeof parsed === "object" && _isValidSha(parsed.baseCommit)) { + return parsed.baseCommit; + } + } catch { + return null; + } + return null; +}; +var main = (startPath = process.cwd()) => { + if (!_isGitRepo()) { + emit({ kind: "skipped", reason: "not-a-git-repository" }, 0); + } + const head = execGit(["rev-parse", "HEAD"]); + if (!_isValidSha(head)) { + emit({ kind: "skipped", reason: "no-commits" }, 0); + } + const inputId = process.argv[2] ?? ""; + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + emit({ kind: "error", detail: `Plan "${inputId}" not found or invalid` }, 2); + } + const { planDir } = resolved; + const reviewDir = path4.join(planDir, "review"); + const filePath = path4.join(reviewDir, "base-commit.json"); + const existing = _readExistingBaseCommit(filePath); + if (existing) { + emit({ kind: "already-captured", baseCommit: existing, file: filePath }, 0); + } + fs4.mkdirSync(reviewDir, { recursive: true }); + const record = { + version: 1, + baseCommit: head, + capturedAt: (/* @__PURE__ */ new Date()).toISOString() + }; + fs4.writeFileSync(filePath, `${JSON.stringify(record)} +`, "utf8"); + emit({ kind: "captured", baseCommit: head, file: filePath }, 0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _isGitRepo, + _isValidSha, + _readExistingBaseCommit, + main +}); diff --git a/.agents/skills/st-execute-blueprint/scripts/check-for-updates.cjs b/.agents/skills/st-execute-blueprint/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs b/.agents/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs new file mode 100644 index 0000000..86c5f43 --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/check-phase-readiness.cjs @@ -0,0 +1,3059 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/check-phase-readiness.ts +var check_phase_readiness_exports = {}; +__export(check_phase_readiness_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_phase_readiness_exports); +var fs5 = __toESM(require("fs")); + +// src/skill-scripts/shared/blueprint-parse.ts +var BLUEPRINT_SECTION_RE = /^##[ \t]+Execution Blueprint[ \t]*$/m; +var PEER_HEADING_RE = /^##[ \t]/m; +var PHASE_HEADING_RE = /^###[ \t]+(?:✅[ \t]*)?Phase[ \t]+(\d+)[ \t]*:?[ \t]*(.*?)[ \t]*$/gm; +var TASK_REF_RE = /Task[ \t]+0*(\d+)/i; +var blueprintSection = (planBody) => { + const sectionMatch = planBody.match(BLUEPRINT_SECTION_RE); + if (!sectionMatch || sectionMatch.index === void 0) return void 0; + const after = planBody.slice(sectionMatch.index + sectionMatch[0].length); + const peer = after.search(PEER_HEADING_RE); + return peer === -1 ? after : after.slice(0, peer); +}; +var parseBlueprintPhases = (planBody) => { + const blueprint = blueprintSection(planBody); + if (blueprint === void 0) return void 0; + const headings = []; + PHASE_HEADING_RE.lastIndex = 0; + let m; + while ((m = PHASE_HEADING_RE.exec(blueprint)) !== null) { + headings.push({ + index: m.index, + afterHeading: m.index + m[0].length, + name: (m[2] ?? "").trim() + }); + } + if (headings.length === 0) return void 0; + const phases = []; + for (let i = 0; i < headings.length; i++) { + const current = headings[i]; + const next = headings[i + 1]; + const end = next ? next.index : blueprint.length; + const segment = blueprint.slice(current.afterHeading, end); + const taskIds = []; + for (const line of segment.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed.startsWith("-") && !trimmed.startsWith("*")) continue; + const ref = trimmed.match(TASK_REF_RE); + if (ref && ref[1] !== void 0) { + const id = parseInt(ref[1], 10); + if (!Number.isNaN(id) && !taskIds.includes(id)) taskIds.push(id); + } + } + phases.push({ + index: i + 1, + name: current.name.length > 0 ? current.name : void 0, + taskIds + }); + } + return phases; +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/task-file.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/task-file.ts +var findTaskFile = (planDir, taskId) => { + const taskDir = path4.join(planDir, "tasks"); + if (!fs4.existsSync(taskDir)) return null; + const idStr = String(taskId); + const variations = [idStr, idStr.padStart(2, "0"), idStr.replace(/^0+/, "") || "0"]; + const uniqueVariations = [...new Set(variations)]; + try { + const files = fs4.readdirSync(taskDir); + return uniqueVariations.reduce((acc, v) => { + if (acc) return acc; + const match = files.find((f) => f.startsWith(`${v}--`) && f.endsWith(".md")); + return match ? path4.join(taskDir, match) : null; + }, null) ?? null; + } catch (_err) { + return null; + } +}; +var TASK_STATUSES = [ + "pending", + "in-progress", + "completed", + "needs-clarification", + "failed" +]; +var MAX_VALUE_PREVIEW = 80; +var describeValue = (value) => { + let text = ""; + const ancestors = []; + const full = () => text.length > MAX_VALUE_PREVIEW; + const write = (node) => { + if (full()) return; + if (typeof node !== "object" || node === null || node instanceof Date) { + text += JSON.stringify(node) ?? String(node); + return; + } + if (ancestors.includes(node)) { + text += '"[Circular]"'; + return; + } + ancestors.push(node); + if (Array.isArray(node)) { + text += "["; + for (let i = 0; i < node.length && !full(); i++) { + if (i > 0) text += ","; + write(node[i] ?? null); + } + text += "]"; + } else { + text += "{"; + let first = true; + for (const [key, item] of Object.entries(node)) { + if (full()) break; + text += `${first ? "" : ","}${JSON.stringify(key)}:`; + first = false; + write(item); + } + text += "}"; + } + ancestors.pop(); + }; + try { + write(value); + } catch { + text = String(value); + } + return text.length > MAX_VALUE_PREVIEW ? `${text.slice(0, MAX_VALUE_PREVIEW)}\u2026` : text; +}; +var isTaskStatus = (value) => typeof value === "string" && TASK_STATUSES.includes(value); +var toTaskId = (value) => { + if (typeof value === "number") return Number.isSafeInteger(value) && value >= 0 ? value : null; + if (typeof value === "string" && /^[0-9]+$/.test(value)) { + const id = Number(value); + return Number.isSafeInteger(id) ? id : null; + } + return null; +}; +var readDependencies = (value) => { + if (value === void 0 || value === null) return []; + if (!Array.isArray(value)) return null; + const ids = []; + for (const item of value) { + const id = toTaskId(item); + if (id === null) return null; + ids.push(id); + } + return ids; +}; +var readTaskMetadata = (markdown) => { + const frontmatter = readYamlFrontmatter(markdown); + if (frontmatter.kind === "none") { + return { kind: "rejected", reason: "task frontmatter not found" }; + } + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + const { status, dependencies } = frontmatter.data; + const expected = TASK_STATUSES.join(", "); + if (status === void 0) { + return { kind: "rejected", reason: `status is missing; expected one of ${expected}` }; + } + if (!isTaskStatus(status)) { + return { + kind: "rejected", + reason: `status ${describeValue(status)} is not one of ${expected}` + }; + } + const ids = readDependencies(dependencies); + if (ids === null) { + return { + kind: "rejected", + reason: `dependencies must be a list of integer task ids; got ${describeValue(dependencies)}` + }; + } + return { kind: "metadata", metadata: { status, dependencies: ids } }; +}; +var readDocument2 = (file) => { + try { + return fs4.readFileSync(file, "utf8"); + } catch (_err) { + return null; + } +}; +var collectTaskReadinessIssues = (planDir, taskId) => { + const idLabel = String(taskId); + const issue = (kind, detail) => ({ + taskId: idLabel, + kind, + detail + }); + const taskFile = findTaskFile(planDir, taskId); + if (!taskFile) return [issue("missing", "task file not found")]; + const taskContent = readDocument2(taskFile); + if (taskContent === null) return [issue("invalid-metadata", "task file could not be read")]; + const task = readTaskMetadata(taskContent); + if (task.kind === "rejected") return [issue("invalid-metadata", task.reason)]; + const issues = []; + if (task.metadata.status === "needs-clarification") { + issues.push(issue("needs-clarification", "status is needs-clarification")); + } + for (const depId of task.metadata.dependencies) { + const depFile = findTaskFile(planDir, depId); + if (!depFile) { + issues.push(issue("unresolved-dependency", `dependency ${depId} not found`)); + continue; + } + const depContent = readDocument2(depFile); + if (depContent === null) { + issues.push(issue("unresolved-dependency", `dependency ${depId} could not be read`)); + continue; + } + const dep = readTaskMetadata(depContent); + if (dep.kind === "rejected") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} has invalid metadata: ${dep.reason}`) + ); + continue; + } + if (dep.metadata.status !== "completed") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} status is ${dep.metadata.status}`) + ); + } + } + return issues; +}; + +// src/skill-scripts/check-phase-readiness.ts +var _printError = (message) => { + console.error(`ERROR: ${message}`); +}; +var _printSuccess = (message) => { + console.log(`\u2713 ${message}`); +}; +var _printInfo = (message) => { + console.log(message); +}; +var main = (startPath = process.cwd()) => { + if (process.argv.length !== 4) { + _printError("Invalid number of arguments"); + console.log("Usage: node check-phase-readiness.cjs "); + console.log("Example: node check-phase-readiness.cjs 16 1"); + process.exit(1); + } + const inputId = process.argv[2]; + const phaseNumber = parseInt(process.argv[3], 10); + if (Number.isNaN(phaseNumber) || phaseNumber < 1) { + _printError("Phase number must be a positive integer"); + process.exit(1); + } + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + _printError(`Plan "${inputId}" not found or invalid`); + process.exit(1); + } + const { planDir, planFile, planId } = resolved; + const planBody = fs5.readFileSync(planFile, "utf8"); + const phases = parseBlueprintPhases(planBody); + if (!phases || phases.length === 0) { + _printError("No Execution Blueprint section with phases found in plan"); + process.exit(1); + } + const phase = phases.find((p) => p.index === phaseNumber); + if (!phase) { + _printError(`Phase ${phaseNumber} not found in plan ${planId}`); + process.exit(1); + } + _printInfo(`Checking phase ${phaseNumber} readiness for plan ${planId}`); + if (phase.name) _printInfo(`Phase name: ${phase.name}`); + if (phase.taskIds.length === 0) { + _printError(`Phase ${phaseNumber} has no tasks listed in the blueprint`); + process.exit(1); + } + _printInfo(`Tasks in phase: ${phase.taskIds.join(", ")}`); + console.log(""); + const allIssues = phase.taskIds.flatMap( + (taskId) => collectTaskReadinessIssues(planDir, taskId).map((issue) => ({ + ...issue, + phaseTaskId: String(taskId) + })) + ); + if (allIssues.length === 0) { + _printSuccess(`Phase ${phaseNumber} is ready to execute`); + process.exit(0); + } + _printError(`Phase ${phaseNumber} is not ready:`); + for (const issue of allIssues) { + console.log(` - Task ${issue.phaseTaskId}: ${issue.detail}`); + } + process.exit(1); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-execute-blueprint/scripts/create-feature-branch.cjs b/.agents/skills/st-execute-blueprint/scripts/create-feature-branch.cjs new file mode 100644 index 0000000..a6dd0bc --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/create-feature-branch.cjs @@ -0,0 +1,386 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/create-feature-branch.ts +var create_feature_branch_exports = {}; +__export(create_feature_branch_exports, { + _extractPlanName: () => _extractPlanName, + _sanitizeBranchName: () => _sanitizeBranchName, + main: () => main +}); +module.exports = __toCommonJS(create_feature_branch_exports); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/git-utils.ts +var import_child_process = require("child_process"); +var GIT_OUTPUT_LIMIT = 64 * 1024 * 1024; +var run = (args, opts) => (0, import_child_process.execFileSync)("git", [...args], { + cwd: opts.cwd, + input: opts.input, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: GIT_OUTPUT_LIMIT +}); +var execGit = (args, opts = {}) => { + try { + const out = run(args, opts); + return opts.trim === false ? out : out.trim(); + } catch { + return null; + } +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/create-feature-branch.ts +var _printError = (message) => { + console.error(`ERROR: ${message}`); +}; +var _printSuccess = (message) => { + console.log(`\u2713 ${message}`); +}; +var _printWarning = (message) => { + console.log(`\u26A0 ${message}`); +}; +var _printInfo = (message) => { + console.log(message); +}; +var _isGitRepo = () => { + const result = execGit(["rev-parse", "--is-inside-work-tree"]); + return result === "true"; +}; +var _getCurrentBranch = () => { + return execGit(["rev-parse", "--abbrev-ref", "HEAD"]); +}; +var _getUncommittedChangesOutsideWorkspace = () => execGit(["status", "--porcelain", "--", ":(top)", ":(top,exclude).ai/strikethroo"]); +var _branchExists = (branchName) => { + const localMatch = execGit(["branch", "--list", branchName]); + if (localMatch) { + const names = localMatch.split("\n").map((b) => b.trim().replace(/^\*\s*/, "")).filter(Boolean); + if (names.includes(branchName)) return true; + } + const remoteMatch = execGit(["branch", "-r", "--list", `origin/${branchName}`]); + if (remoteMatch && remoteMatch.trim().length > 0) return true; + return false; +}; +var _sanitizeBranchName = (planName) => { + return planName.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").substring(0, 60); +}; +var _extractPlanName = (planDir) => { + const dirName = path4.basename(planDir); + const match = dirName.match(/^\d+--(.+)$/); + return match && match[1] ? match[1] : dirName; +}; +var main = (startPath = process.cwd()) => { + if (process.argv.length < 3) { + _printError("Missing plan ID argument"); + console.log("Usage: node create-feature-branch.cjs "); + console.log("Example: node create-feature-branch.cjs 58"); + process.exit(1); + } + const inputId = process.argv[2]; + if (!_isGitRepo()) { + _printError("Not a git repository"); + process.exit(1); + } + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + _printError(`Plan "${inputId}" not found or invalid`); + process.exit(1); + } + const { planDir, planId } = resolved; + _printInfo(`Found plan: ${path4.basename(planDir)}`); + const currentBranch = _getCurrentBranch(); + if (!currentBranch) { + _printError("Could not determine current git branch"); + process.exit(1); + } + if (currentBranch !== "main" && currentBranch !== "master") { + _printWarning(`Not on main/master branch (current: ${currentBranch})`); + _printInfo("Proceeding without creating a new branch"); + process.exit(0); + } + const outsideWorkspaceStatus = _getUncommittedChangesOutsideWorkspace(); + if (outsideWorkspaceStatus === null) { + _printError("Could not inspect git status; branch creation has been blocked"); + process.exit(1); + } + if (outsideWorkspaceStatus.length > 0) { + _printError("Uncommitted changes detected outside .ai/strikethroo"); + _printInfo("Commit or stash changes outside .ai/strikethroo before creating a feature branch"); + process.exit(1); + } + const planName = _extractPlanName(planDir); + const sanitizedName = _sanitizeBranchName(planName); + const branchName = `feature/${planId}--${sanitizedName}`; + if (_branchExists(branchName)) { + if (currentBranch === branchName) { + _printSuccess(`Already on branch: ${branchName}`); + process.exit(0); + } + _printWarning(`Branch "${branchName}" already exists`); + const checkoutResult = execGit(["checkout", branchName]); + if (checkoutResult === null) { + _printError(`Failed to checkout branch "${branchName}"`); + process.exit(1); + } + _printSuccess(`Switched to existing branch: ${branchName}`); + process.exit(0); + } + const createResult = execGit(["checkout", "-b", branchName]); + if (createResult === null) { + _printError(`Failed to create branch "${branchName}"`); + process.exit(1); + } + _printSuccess(`Created and switched to branch: ${branchName}`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _extractPlanName, + _sanitizeBranchName, + main +}); diff --git a/.agents/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs b/.agents/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs new file mode 100755 index 0000000..14ea3e5 --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/dispatch-task-execution.cjs @@ -0,0 +1,3688 @@ +#!/usr/bin/env node +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/dispatch-task-execution.ts +var dispatch_task_execution_exports = {}; +__export(dispatch_task_execution_exports, { + resolveDispatchRoute: () => resolveDispatchRoute +}); +module.exports = __toCommonJS(dispatch_task_execution_exports); +var fs5 = __toESM(require("fs")); +var path7 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/dispatch-target-selector.ts +var path = __toESM(require("path")); +var import_child_process = require("child_process"); +var executionTargetId = (target) => JSON.stringify([target.model, target.harness ?? null, target.reasoning_effort ?? null]); +var runSelector = (scriptPath, input, timeoutMs) => { + try { + const nodeScript = /\.(?:cjs|mjs|js)$/.test(scriptPath); + const stdout = nodeScript ? (0, import_child_process.execFileSync)(process.execPath, [scriptPath], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }) : (0, import_child_process.execFileSync)(scriptPath, [], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }); + return { ok: true, stdout }; + } catch { + return { ok: false }; + } +}; +var nativeDefault = (reason, detail) => ({ kind: "native-default", reason, detail }); +var resolveRepositoryScript = (projectRoot, configured) => { + if (path.isAbsolute(configured)) return null; + const root = path.resolve(projectRoot); + const resolved = path.resolve(root, configured); + return resolved === root || resolved.startsWith(`${root}${path.sep}`) ? resolved : null; +}; +var selectDispatchTarget = (config, profileName, avoidedIds, options) => { + const profile = config.profiles.find((candidate) => candidate.name === profileName); + if (!profile) { + return nativeDefault( + "profile-unavailable", + `Execution profile "${profileName}" is not present in current configuration.` + ); + } + const candidates = profile.targets.filter( + (target) => config.allowExternalHarnessExecution || target.harness === void 0 || target.harness === options.currentHarness + ).map((target) => ({ id: executionTargetId(target), target })); + if (candidates.length === 0) { + return nativeDefault( + "targets-exhausted", + `Execution profile "${profileName}" has no targets for the current harness while external harness execution is disabled.` + ); + } + const available = candidates.filter((candidate) => !avoidedIds.has(candidate.id)); + if (available.length === 0) { + return nativeDefault( + "targets-exhausted", + `All ${candidates.length} configured target(s) for profile "${profileName}" were avoided.` + ); + } + if (config.resolverScript === void 0) { + const selected2 = available[0]; + return { kind: "selected", ...selected2, source: "built-in" }; + } + const scriptPath = resolveRepositoryScript(options.projectRoot, config.resolverScript); + if (!scriptPath) { + return nativeDefault( + "selector-failure", + "Custom target selector path is not repository-relative." + ); + } + const input = { + version: 1, + task: { id: options.taskId, profile: profileName }, + candidates, + avoid: [...avoidedIds].sort() + }; + const result = (options.runSelector ?? runSelector)( + scriptPath, + JSON.stringify(input), + options.timeoutMs ?? 1e4 + ); + if (!result.ok || result.stdout === void 0) { + return nativeDefault( + "selector-failure", + "Custom target selector did not complete successfully." + ); + } + let output; + try { + output = JSON.parse(result.stdout); + } catch { + return nativeDefault("selector-failure", "Custom target selector returned invalid JSON."); + } + if (typeof output !== "object" || output === null || Array.isArray(output) || Object.keys(output).length !== 1 || typeof output.target !== "string") { + return nativeDefault("selector-failure", "Custom target selector returned an invalid result."); + } + const selectedId = output.target; + const selected = candidates.find((candidate) => candidate.id === selectedId); + if (!selected || avoidedIds.has(selected.id)) { + return nativeDefault( + "selector-failure", + "Custom target selector returned an unknown or avoided target." + ); + } + return { kind: "selected", ...selected, source: "custom" }; +}; + +// src/skill-scripts/shared/external-dispatch.ts +var path3 = __toESM(require("path")); +var import_child_process2 = require("child_process"); + +// src/skill-scripts/shared/executable-resolution.ts +var fs = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var DEFAULT_PATHEXT = ".EXE;.CMD;.BAT;.COM"; +var hasPathSeparator = (executable) => /[\\/]/.test(executable); +var resolveExecutablePath = (executable, environment = {}) => { + const env = environment.env ?? process.env; + const platform = environment.platform ?? process.platform; + const win32 = platform === "win32"; + const suffixes = win32 ? ["", ...(env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean)] : [""]; + const directories = hasPathSeparator(executable) ? [""] : (env.PATH ?? "").split(path2.delimiter).filter(Boolean); + const mode = win32 ? fs.constants.F_OK : fs.constants.X_OK; + for (const directory of directories) { + for (const suffix of suffixes) { + const candidate = path2.resolve(directory, `${executable}${suffix}`); + try { + fs.accessSync(candidate, mode); + if (fs.statSync(candidate).isFile()) return fs.realpathSync(candidate); + } catch { + } + } + } + return null; +}; +var executableResolves = (executable, environment) => resolveExecutablePath(executable, environment) !== null; + +// src/skill-scripts/shared/external-dispatch.ts +var taskPrompt = (request) => `Strikethroo external task dispatch \u2014 Plan ${request.planId}, Task ${request.taskId}. +Workspace: ${request.workspace} +Task file: ${request.taskFile} +You are a delegated execution worker. Do not run check-for-updates.cjs or emit update notices. +Before implementation, read and execute ${path3.join( + request.workspace, + ".ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md" +)}. Halt if that hook fails. + +Read and implement this task. Preserve dependency validation, status transitions, evidence reporting, and error-hook handling. Report failures clearly. + +${request.taskMarkdown}`; +var command = (executable, argv, request) => ({ + executable, + argv, + cwd: request.workspace, + stdin: request.prompt +}); +var modelArgv = (model) => model === void 0 ? [] : ["--model", model]; +var EXTERNAL_HARNESS_ADAPTERS = { + claude: { + executable: "claude", + buildCommand: (request) => command( + "claude", + [ + "-p", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--effort", request.reasoningEffort] + ], + request + ), + authenticationArgv: () => ["auth", "status"] + }, + codex: { + executable: "codex", + buildCommand: (request) => command( + "codex", + [ + "exec", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--config", `model_reasoning_effort=${request.reasoningEffort}`], + "-" + ], + request + ), + authenticationArgv: () => ["login", "status"] + }, + cursor: { + executable: "cursor-agent", + buildCommand: (request) => command( + "cursor-agent", + ["--print", ...request.cliArgs, ...modelArgv(request.model)], + request + ), + authenticationArgv: () => ["status"] + }, + gemini: { + executable: "gemini", + // The empty positional prompt is the existing contract — content travels on + // stdin. It stays even when the model pair is dropped. + buildCommand: (request) => command("gemini", ["--prompt", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + copilot: { + executable: "copilot", + buildCommand: (request) => command("copilot", ["-p", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + opencode: { + executable: "opencode", + buildCommand: (request) => command( + "opencode", + [ + "run", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--variant", request.reasoningEffort], + "-" + ], + request + ), + authenticationArgv: () => ["auth", "list"] + } +}; +var adapterKeys = Object.keys(EXTERNAL_HARNESS_ADAPTERS).sort(); +var harnessKeys = [...SUPPORTED_HARNESSES].sort(); +if (adapterKeys.join("\0") !== harnessKeys.join("\0")) { + throw new Error("External harness adapter registry does not cover SUPPORTED_HARNESSES exactly."); +} +var taskCommandRequest = (request) => ({ + cliArgs: request.cliArgs ?? [], + model: request.model, + reasoningEffort: request.reasoningEffort, + workspace: request.workspace, + prompt: taskPrompt(request) +}); +var CAPTURED_STDOUT_LIMIT = 262144; +var AUTHENTICATION_TIMEOUT_MS = 3e4; +var STDIO_SLOTS = { + ignore: { stdout: "ignore" }, + inherit: { stdout: "inherit" }, + capture: { stdout: "pipe" } +}; +var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore", timeoutMs) => new Promise((resolve4, reject) => { + let settled = false; + const child = (0, import_child_process2.spawn)(executable, argv, { + cwd, + shell: false, + stdio: [ + stdin === void 0 ? "ignore" : "pipe", + STDIO_SLOTS[outputMode].stdout, + outputMode === "ignore" ? "ignore" : "inherit" + ] + }); + const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => { + if (settled) return; + settled = true; + child.kill("SIGKILL"); + resolve4({ exitCode: 1, timedOut: true }); + }, timeoutMs); + const settle = (outcome2) => { + if (settled) return; + settled = true; + clearTimeout(timer); + resolve4(outcome2); + }; + const fail = (error) => { + if (settled) return; + settled = true; + clearTimeout(timer); + reject(error); + }; + let captured = ""; + if (outputMode === "capture") { + child.stdout.setEncoding("utf8"); + child.stdout.once("error", fail); + child.stdout.on("data", (chunk) => { + process.stderr.write(chunk); + captured += chunk; + if (captured.length > CAPTURED_STDOUT_LIMIT) { + captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT); + } + }); + } + child.once("error", fail); + child.once("close", (code) => { + settle({ + exitCode: code ?? 1, + ...outputMode === "capture" ? { stdout: captured } : {} + }); + }); + if (stdin !== void 0) { + child.stdin.once("error", fail); + try { + child.stdin.end(stdin); + } catch (error) { + fail(error instanceof Error ? error : new Error(String(error))); + } + } +}); +var authenticateHarness = async (commandSpec, adapter, timeoutMs = AUTHENTICATION_TIMEOUT_MS) => { + const executable = commandSpec.executable; + try { + const result = await runProcess( + executable, + adapter.authenticationArgv(), + commandSpec.cwd, + void 0, + "ignore", + timeoutMs + ); + if (result.timedOut === true) { + return { + ok: false, + detail: `${executable} authentication check timed out after ${timeoutMs} ms and was terminated.` + }; + } + return result.exitCode === 0 ? { ok: true } : { + ok: false, + detail: `${executable} authentication check failed: exited ${result.exitCode}.` + }; + } catch (error) { + const code = error.code; + return { + ok: false, + detail: `${executable} authentication check could not launch${code === void 0 ? "" : ` (${code})`}: ${errorMessage(error)}` + }; + } +}; +var dependencies = { + executableExists: executableResolves, + authenticate: authenticateHarness, + launch: (commandSpec, options) => runProcess( + commandSpec.executable, + commandSpec.argv, + commandSpec.cwd, + commandSpec.stdin, + options?.captureStdout === true ? "capture" : "inherit" + ) +}; +var errorMessage = (error) => error instanceof Error ? error.message : String(error); +var prepareLaunch = async (harness, input, active, guard) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + if (!adapter) { + return { + kind: "fallback", + reason: "adapter-unavailable", + detail: `No adapter is registered for ${harness}.` + }; + } + const blocked = guard?.(); + if (blocked) return blocked; + const executable = adapter.executable; + if (!active.executableExists(executable)) { + return { + kind: "fallback", + reason: "executable-unavailable", + detail: `${executable} is unavailable.` + }; + } + const commandSpec = adapter.buildCommand(input); + const authentication = await active.authenticate(commandSpec, adapter); + if (!authentication.ok) { + return { + kind: "fallback", + reason: "authentication-failed", + detail: authentication.detail ?? `${adapter.executable} authentication check failed.` + }; + } + return { kind: "ready", command: commandSpec }; +}; +var launchPrepared = async (prepared, active, label, captureStdout = false) => { + if (prepared.kind === "fallback") return prepared; + try { + const launched = await active.launch(prepared.command, { captureStdout }); + const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout }; + return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout }; + } catch (error) { + return { + kind: "infrastructure-failure", + detail: `External ${label} process failed: ${errorMessage(error)}` + }; + } +}; +var unsupportedReasoningEffort = (request) => request.reasoningEffort !== void 0 && (request.harness === "cursor" || request.harness === "gemini" || request.harness === "copilot") ? { + kind: "fallback", + reason: "unsupported-reasoning-effort", + detail: `${request.harness} does not support a generic reasoning_effort override.` +} : void 0; +var dispatchExternalTask = async (request, overrides = {}) => { + const active = { ...dependencies, ...overrides }; + const prepared = await prepareLaunch( + request.harness, + taskCommandRequest(request), + active, + () => unsupportedReasoningEffort(request) + ); + return launchPrepared(prepared, active, "task"); +}; + +// src/skill-scripts/shared/harness-availability.ts +var import_crypto2 = require("crypto"); +var import_child_process3 = require("child_process"); +var fs4 = __toESM(require("fs")); +var os = __toESM(require("os")); +var path6 = __toESM(require("path")); + +// src/skill-scripts/shared/harness-configuration.ts +var import_crypto = require("crypto"); +var fs3 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/execution-routing.ts +var fs2 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); +var EXECUTION_ROUTING_SECTION = "execution_routing"; +var isPlainObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0; +var validateTarget = (profileName, index, raw, supportedHarnesses, errors) => { + const label = `profile "${profileName}" models[${index}]`; + if (!isPlainObject3(raw)) { + errors.push(`${label} must be a mapping with an exact "model" string.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "model" && key !== "harness" && key !== "reasoning_effort") { + errors.push(`${label} has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.model)) { + errors.push(`${label} requires a non-empty exact "model" string.`); + return null; + } + const target = { model: raw.model }; + if ("harness" in raw) { + if (!isNonEmptyString(raw.harness)) { + errors.push(`${label} "harness" must be a non-empty string when provided.`); + return null; + } + if (!supportedHarnesses.includes(raw.harness)) { + errors.push(`${label} harness "${raw.harness}" is not a supported harness.`); + return null; + } + target.harness = raw.harness; + } + if ("reasoning_effort" in raw) { + if (!isNonEmptyString(raw.reasoning_effort)) { + errors.push(`${label} "reasoning_effort" must be a non-empty string when provided.`); + return null; + } + target.reasoning_effort = raw.reasoning_effort; + } + return target; +}; +var validateProfile = (name, raw, supportedHarnesses, errors) => { + if (!isPlainObject3(raw)) { + errors.push(`profile "${name}" must be a mapping with "description" and "models".`); + return null; + } + if ("resolver" in raw) { + errors.push( + `profile "${name}" configures a per-profile resolver; only the single top-level "resolver" is supported.` + ); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "description" && key !== "models") { + errors.push(`profile "${name}" has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.description)) { + errors.push(`profile "${name}" requires a non-empty LLM-facing "description".`); + return null; + } + if (!Array.isArray(raw.models) || raw.models.length === 0) { + errors.push(`profile "${name}" requires a non-empty ordered "models" array.`); + return null; + } + const targets = []; + for (let i = 0; i < raw.models.length; i += 1) { + const target = validateTarget(name, i, raw.models[i], supportedHarnesses, errors); + if (!target) return null; + targets.push(target); + } + return { name, description: raw.description.trim(), targets }; +}; +var loadRoutingConfig = (strikethrooRoot, supportedHarnesses) => { + const configPath = path4.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs2.readFileSync(configPath, "utf8"); + } catch { + return { kind: "no-config" }; + } + if (!hasYamlContent(contents)) return { kind: "disabled" }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) return { kind: "disabled" }; + if (!isPlainObject3(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[EXECUTION_ROUTING_SECTION]; + if (section === null || section === void 0) return { kind: "disabled" }; + const errors = []; + if (!isPlainObject3(section)) { + return { + kind: "invalid", + errors: [`config.yaml "${EXECUTION_ROUTING_SECTION}" must be a YAML mapping.`] + }; + } + for (const key of Object.keys(section)) { + if (key !== "enabled" && key !== "allow_external_harness_execution" && key !== "profiles" && key !== "resolver") { + errors.push(`${EXECUTION_ROUTING_SECTION} has unknown key "${key}".`); + } + } + if ("allow_external_harness_execution" in section && typeof section.allow_external_harness_execution !== "boolean") { + errors.push( + `${EXECUTION_ROUTING_SECTION} "allow_external_harness_execution" must be true or false.` + ); + } + if ("enabled" in section) { + if (typeof section.enabled !== "boolean") { + errors.push(`${EXECUTION_ROUTING_SECTION} "enabled" must be true or false.`); + return { kind: "invalid", errors }; + } + if (!section.enabled) + return errors.length > 0 ? { kind: "invalid", errors } : { kind: "disabled" }; + } + const rawProfiles = "profiles" in section && section.profiles == null ? {} : section.profiles; + if (!("profiles" in section) || !isPlainObject3(rawProfiles)) { + errors.push(`${EXECUTION_ROUTING_SECTION} requires a "profiles" mapping.`); + return { kind: "invalid", errors }; + } + const profiles = []; + for (const [name, rawProfile] of Object.entries(rawProfiles)) { + const profile = validateProfile(name, rawProfile, supportedHarnesses, errors); + if (profile) profiles.push(profile); + } + let resolverScript; + if ("resolver" in section) { + const resolver = section.resolver; + if (!isPlainObject3(resolver) || !isNonEmptyString(resolver.script)) { + errors.push('resolver must be a mapping with a non-empty "script" path.'); + } else { + for (const key of Object.keys(resolver)) { + if (key !== "script") errors.push(`resolver has unknown key "${key}".`); + } + resolverScript = resolver.script; + } + } + if (errors.length > 0) return { kind: "invalid", errors }; + if (profiles.length === 0) return { kind: "disabled" }; + const config = { + allowExternalHarnessExecution: section.allow_external_harness_execution === true, + profiles + }; + if (resolverScript !== void 0) config.resolverScript = resolverScript; + return { kind: "config", config }; +}; + +// src/skill-scripts/shared/harness-configuration.ts +var HARNESS_CONFIGURATION_SECTION = "harnesses"; +var HARNESS_CONFIGURATION_NORMALIZATION_VERSION = 1; +var isPlainObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var hashHarnessCliArgs = (harness, cliArgs, normalizationVersion = HARNESS_CONFIGURATION_NORMALIZATION_VERSION) => (0, import_crypto.createHash)("sha256").update( + JSON.stringify({ + schema: normalizationVersion, + harness, + cliArgs + }), + "utf8" +).digest("hex"); +var normalizeInvocation = (harness, cliArgs) => { + const immutableArgs = Object.freeze([...cliArgs]); + return Object.freeze({ + cliArgs: immutableArgs, + cliArgsHash: hashHarnessCliArgs(harness, immutableArgs) + }); +}; +var emptyConfiguration = () => Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, normalizeInvocation(harness, [])]) + ) +); +var validateHarnessEntry = (harness, raw, errors) => { + const entryPath = `config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness}`; + if (!isPlainObject4(raw)) { + errors.push(`${entryPath} must be a mapping.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "cli_args") errors.push(`${entryPath}.${key} is not supported.`); + } + if (!("cli_args" in raw)) return normalizeInvocation(harness, []); + if (!Array.isArray(raw.cli_args)) { + errors.push(`${entryPath}.cli_args must be an array of exact strings.`); + return null; + } + const cliArgs = []; + raw.cli_args.forEach((value, index) => { + const valuePath = `${entryPath}.cli_args[${index}]`; + if (typeof value !== "string" || value.length === 0) { + errors.push(`${valuePath} must be a non-empty string.`); + return; + } + if (value.includes("\0")) { + errors.push(`${valuePath} must not contain a NUL character.`); + return; + } + cliArgs.push(value); + }); + return normalizeInvocation(harness, cliArgs); +}; +var loadHarnessConfiguration = (strikethrooRoot) => { + const configPath = path5.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs3.readFileSync(configPath, "utf8"); + } catch (error) { + if (error.code === "ENOENT") { + return { kind: "config", config: emptyConfiguration() }; + } + return { + kind: "invalid", + errors: [ + `config.yaml could not be read: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (!hasYamlContent(contents)) return { kind: "config", config: emptyConfiguration() }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[HARNESS_CONFIGURATION_SECTION]; + if (section === null || section === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(section)) { + return { + kind: "invalid", + errors: [`config.yaml ${HARNESS_CONFIGURATION_SECTION} must be a YAML mapping.`] + }; + } + const errors = []; + const supportedHarnesses = new Set(SUPPORTED_HARNESSES); + for (const harness of Object.keys(section)) { + if (!supportedHarnesses.has(harness)) { + errors.push(`config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness} is not supported.`); + } + } + const entries = {}; + for (const harness of SUPPORTED_HARNESSES) { + if (!(harness in section)) { + entries[harness] = normalizeInvocation(harness, []); + continue; + } + const entry = validateHarnessEntry(harness, section[harness], errors); + if (entry) entries[harness] = entry; + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "config", config: Object.freeze(entries) }; +}; + +// src/skill-scripts/shared/harness-availability.ts +var AVAILABILITY_REGISTRY_VERSION = 4; +var AVAILABLE_TTL_MS = 30 * 60 * 1e3; +var UNAVAILABLE_TTL_MS = 5 * 60 * 1e3; +var PROBE_TIMEOUT_MS = 2e4; +var AVAILABILITY_CACHE_RELATIVE_PATH = path6.join("runtime", "harness-availability.json"); +var CACHE_VERSION = 2; +var availabilityDefinition = (harness) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + return { + executable: adapter.executable, + buildCommand: (cwd, cliArgs, prompt) => adapter.buildCommand({ cliArgs, workspace: cwd, prompt }) + }; +}; +var HARNESS_AVAILABILITY_REGISTRY = Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, availabilityDefinition(harness)]) + ) +); +var runProbe = (command2, timeoutMs) => new Promise((resolve4) => { + let stdout = ""; + let stderr = ""; + let settled = false; + let timedOut = false; + const finish = (result) => { + if (settled) return; + settled = true; + resolve4(result); + }; + const child = (0, import_child_process3.spawn)(command2.executable, command2.argv, { + cwd: command2.cwd, + shell: false, + stdio: ["pipe", "pipe", "pipe"] + }); + child.stdout?.setEncoding("utf8"); + child.stderr?.setEncoding("utf8"); + child.stdout?.on("data", (chunk) => { + stdout = (stdout + chunk).slice(-4096); + }); + child.stderr?.on("data", (chunk) => { + stderr = (stderr + chunk).slice(-4096); + }); + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGKILL"); + child.stdout?.destroy(); + child.stderr?.destroy(); + finish({ exitCode: 1, timedOut, stdout, stderr }); + }, timeoutMs); + child.once("error", (error) => { + clearTimeout(timer); + finish({ exitCode: 1, timedOut, stdout, stderr, error: error.message }); + }); + child.once("close", (code) => { + clearTimeout(timer); + finish({ exitCode: code ?? 1, timedOut, stdout, stderr }); + }); + child.stdin?.on("error", () => void 0); + child.stdin?.end(command2.stdin); +}); +var probeFailureReason = (probe) => { + const reason = probe.timedOut ? `Harness readiness check timed out after ${PROBE_TIMEOUT_MS} ms.` : probe.error ? `Harness readiness check could not launch: ${probe.error}` : probe.exitCode !== 0 ? `Harness readiness check exited ${probe.exitCode}.` : "Harness exited 0 but did not create the required readiness file with the expected content."; + const diagnostics = [ + probe.stderr?.trim() ? `stderr: ${probe.stderr.trim().slice(-4096)}` : "", + probe.stdout?.trim() ? `stdout: ${probe.stdout.trim().slice(-4096)}` : "" + ].filter(Boolean); + return [reason, ...diagnostics].join(" "); +}; +var defaultDependencies = { + now: Date.now, + resolveExecutable: resolveExecutablePath, + runProbe +}; +var isHarness = (value) => typeof value === "string" && SUPPORTED_HARNESSES.includes(value); +var isCacheEntry = (value) => { + if (!value || typeof value !== "object") return false; + const entry = value; + return typeof entry.key === "string" && isHarness(entry.harness) && typeof entry.available === "boolean" && typeof entry.observedAt === "number" && Number.isFinite(entry.observedAt) && typeof entry.expiresAt === "number" && Number.isFinite(entry.expiresAt) && typeof entry.reason === "string"; +}; +var emptyCache = () => ({ version: CACHE_VERSION, entries: [] }); +var readCache = (cachePath) => { + try { + const parsed = JSON.parse(fs4.readFileSync(cachePath, "utf8")); + if (!parsed || typeof parsed !== "object") return emptyCache(); + const record = parsed; + if (record.version !== CACHE_VERSION || !Array.isArray(record.entries)) return emptyCache(); + return { version: CACHE_VERSION, entries: record.entries.filter(isCacheEntry) }; + } catch { + return emptyCache(); + } +}; +var writeCache = (cachePath, entry) => { + fs4.mkdirSync(path6.dirname(cachePath), { recursive: true }); + const cache = readCache(cachePath); + const existingIndex = cache.entries.findIndex((candidate) => candidate.key === entry.key); + if (existingIndex === -1) cache.entries.push(entry); + else if (cache.entries[existingIndex].observedAt <= entry.observedAt) { + cache.entries[existingIndex] = entry; + } + const temporary = `${cachePath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.tmp`; + try { + fs4.writeFileSync(temporary, `${JSON.stringify(cache, null, 2)} +`, { mode: 384 }); + fs4.renameSync(temporary, cachePath); + } finally { + try { + fs4.unlinkSync(temporary); + } catch { + } + } +}; +var cacheKey = (harness, executableIdentity, invocation) => (0, import_crypto2.createHash)("sha256").update( + JSON.stringify({ + harness, + executableIdentity, + cliArgsHash: invocation.cliArgsHash, + normalizationVersion: HARNESS_CONFIGURATION_NORMALIZATION_VERSION, + probeRegistryVersion: AVAILABILITY_REGISTRY_VERSION + }) +).digest("hex"); +var readinessEvidence = () => { + const nonce = (0, import_crypto2.randomUUID)(); + return { + file: "strikethroo-readiness.txt", + content: `strikethroo-readiness:${nonce} +` + }; +}; +var readinessPrompt = (evidence) => `Run a shell command that creates ${evidence.file} in the current workspace with the exact UTF-8 content ${JSON.stringify(evidence.content)}. Do not use a file editing tool. +STRIKETHROO_READINESS=${JSON.stringify(evidence)} +`; +var initializeProbeWorkspace = () => { + const workspace = fs4.mkdtempSync(path6.join(os.tmpdir(), "strikethroo-harness-probe-")); + const initialized = (0, import_child_process3.spawnSync)("git", ["init", "--quiet"], { + cwd: workspace, + shell: false, + stdio: "ignore", + timeout: 5e3 + }); + if (initialized.status === 0 && !initialized.error) return workspace; + fs4.rmSync(workspace, { recursive: true, force: true }); + return void 0; +}; +var hasReadinessEvidence = (workspace, evidence) => { + const target = path6.join(workspace, evidence.file); + try { + return fs4.lstatSync(target).isFile() && fs4.readFileSync(target, "utf8") === evidence.content; + } catch { + return false; + } +}; +var outcome = (harness, available, now, reason) => ({ + harness, + available, + observedAt: now, + expiresAt: now + (available ? AVAILABLE_TTL_MS : UNAVAILABLE_TTL_MS), + reason, + source: "probe" +}); +var invocationFor = (request, harness) => { + if (request.invocation) return request.invocation; + const loaded = loadHarnessConfiguration(request.strikethrooRoot); + return loaded.kind === "config" ? loaded.config[harness] : void 0; +}; +var checkHarnessAvailability = async (request, overrides = {}) => { + const active = { ...defaultDependencies, ...overrides }; + const now = active.now(); + if (request.harness === void 0 || request.harness === request.currentHarness) { + return { + harness: request.harness ?? request.currentHarness, + available: true, + observedAt: now, + expiresAt: now, + reason: "Native/current harness targets do not require a probe.", + source: "bypass" + }; + } + const harness = request.harness; + const invocation = invocationFor(request, harness); + if (!invocation) return outcome(harness, false, now, "Harness configuration is invalid."); + const definition = HARNESS_AVAILABILITY_REGISTRY[harness]; + const executableIdentity = active.resolveExecutable(definition.executable); + if (!executableIdentity) + return outcome( + harness, + false, + now, + `Harness executable '${definition.executable}' was not found on PATH.` + ); + const key = cacheKey(harness, executableIdentity, invocation); + const cachePath = path6.join(request.strikethrooRoot, AVAILABILITY_CACHE_RELATIVE_PATH); + const cached = readCache(cachePath).entries.find( + (entry) => entry.key === key && entry.expiresAt > now + ); + if (cached) { + const { key: _key, ...cachedOutcome } = cached; + return { ...cachedOutcome, source: "cache" }; + } + const complete = (result) => { + const { source: _source, ...cacheEntry } = result; + try { + writeCache(cachePath, { key, ...cacheEntry }); + } catch { + } + return result; + }; + const probeWorkspace = initializeProbeWorkspace(); + if (!probeWorkspace) { + return complete( + outcome( + harness, + false, + now, + "Could not initialize the disposable Git workspace for the readiness check." + ) + ); + } + try { + const evidence = readinessEvidence(); + const command2 = definition.buildCommand( + probeWorkspace, + invocation.cliArgs, + readinessPrompt(evidence) + ); + const probe = await active.runProbe( + { ...command2, executable: executableIdentity }, + PROBE_TIMEOUT_MS + ); + const available = probe.exitCode === 0 && !probe.timedOut && hasReadinessEvidence(probeWorkspace, evidence); + return complete( + outcome( + harness, + available, + now, + available ? "Harness readiness verified." : probeFailureReason(probe) + ) + ); + } finally { + fs4.rmSync(probeWorkspace, { recursive: true, force: true }); + } +}; + +// src/skill-scripts/dispatch-task-execution.ts +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var errorMessage2 = (error) => error instanceof Error ? error.message : String(error); +var encodeHandoff = (route) => Buffer.from(JSON.stringify({ version: 1, ...route }), "utf8").toString("base64url"); +var decodeHandoff = (encoded) => { + let raw; + try { + raw = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8")); + } catch { + throw new Error("Resolved execution handoff is not valid encoded JSON."); + } + if (!raw || typeof raw !== "object" || Array.isArray(raw)) { + throw new Error("Resolved execution handoff must be an object."); + } + const value = raw; + const allowed = ["version", "kind", "harness", "model", "reasoningEffort"]; + if (Object.keys(value).some((key) => !allowed.includes(key)) || value.version !== 1 || value.kind !== "external-override" || typeof value.harness !== "string" || !SUPPORTED_HARNESSES.includes(value.harness) || typeof value.model !== "string" || value.model.length === 0 || "reasoningEffort" in value && typeof value.reasoningEffort !== "string") { + throw new Error("Resolved execution handoff has an invalid shape."); + } + return value; +}; +var externalRoute = (harness, model, reasoningEffort) => { + const exact = { + kind: "external-override", + harness, + model, + ...reasoningEffort === void 0 ? {} : { reasoningEffort } + }; + return { ...exact, handoff: encodeHandoff(exact) }; +}; +var readProfile = (taskMarkdown) => { + const frontmatter = readYamlFrontmatter(taskMarkdown); + if (frontmatter.kind === "none") return { kind: "profile" }; + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + if (!Object.prototype.hasOwnProperty.call(frontmatter.data, "execution_profile")) { + return { kind: "profile" }; + } + const profile = frontmatter.data.execution_profile; + if (typeof profile !== "string" || profile.trim() === "") { + return { kind: "rejected", reason: "execution_profile must be a non-empty string." }; + } + return { kind: "profile", profile }; +}; +var resolveDispatchRoute = async (request) => { + const read = readProfile(request.taskMarkdown); + if (read.kind === "rejected") { + return { kind: "infrastructure-failure", detail: `Task metadata rejected: ${read.reason}` }; + } + const profile = read.profile; + if (profile === void 0) return { kind: "native-default" }; + const configResult = loadRoutingConfig(request.strikethrooRoot, SUPPORTED_HARNESSES); + if (configResult.kind !== "config") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: configResult.kind === "invalid" ? `Execution routing configuration is invalid: ${configResult.errors.join(" ")}` : `Execution profile "${profile}" cannot be resolved because routing is disabled.` + }; + } + const avoided = /* @__PURE__ */ new Set(); + const unavailable = []; + let harnessConfiguration; + const candidateCount = configResult.config.profiles.find((candidate) => candidate.name === profile)?.targets.length ?? 0; + for (let attempt = 0; attempt < Math.max(1, candidateCount); attempt += 1) { + const selection = selectDispatchTarget(configResult.config, profile, avoided, { + currentHarness: request.currentHarness, + projectRoot: request.workspace, + taskId: request.taskId + }); + if (selection.kind === "native-default") { + return { kind: "fallback", reason: selection.reason, detail: selection.detail }; + } + const harness = selection.target.harness; + if (harness === void 0 || harness === request.currentHarness) { + return { + kind: "native-override", + model: selection.target.model, + ...selection.target.reasoning_effort === void 0 ? {} : { reasoningEffort: selection.target.reasoning_effort } + }; + } + harnessConfiguration ??= loadHarnessConfiguration(request.strikethrooRoot); + if (harnessConfiguration.kind === "invalid") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: `Harness invocation configuration is invalid: ${harnessConfiguration.errors.join( + " " + )}` + }; + } + const invocation = harnessConfiguration.config[harness]; + const availability = await checkHarnessAvailability({ + strikethrooRoot: request.strikethrooRoot, + workspace: request.workspace, + harness, + currentHarness: request.currentHarness, + invocation + }); + if (availability.available) { + return externalRoute(harness, selection.target.model, selection.target.reasoning_effort); + } + unavailable.push( + `${harness} (${availability.source === "probe" ? "fresh" : availability.source})` + ); + avoided.add(selection.id); + } + return { + kind: "fallback", + reason: "invalid-execution", + detail: `All configured targets for execution profile "${profile}" are unavailable or exhausted.` + (unavailable.length === 0 ? "" : ` Observations: ${unavailable.join("; ")}`) + }; +}; +var main = async () => { + const args = process.argv.slice(2); + const mode = args.shift(); + if (mode !== "resolve" && mode !== "execute" || args.length < (mode === "execute" ? 6 : 5)) { + emit( + { + kind: "infrastructure-failure", + detail: "Usage: dispatch-task-execution.cjs resolve | execute " + }, + 2 + ); + } + const handoffArg = mode === "execute" ? args.shift() : void 0; + const [taskFile, currentHarnessRaw, workspace, planId, taskId] = args; + if (!taskFile || !currentHarnessRaw || !workspace || !planId || !taskId || !SUPPORTED_HARNESSES.includes(currentHarnessRaw)) { + emit({ kind: "infrastructure-failure", detail: "Task dispatch arguments are invalid." }, 2); + } + const validTaskFile = taskFile; + const validCurrentHarness = currentHarnessRaw; + const validWorkspace = workspace; + const validPlanId = planId; + const validTaskId = taskId; + const taskPath = path7.resolve(validTaskFile); + const taskMarkdown = fs5.readFileSync(taskPath, "utf8"); + if (mode === "resolve") { + const route = await resolveDispatchRoute({ + taskMarkdown, + currentHarness: validCurrentHarness, + workspace: path7.resolve(validWorkspace), + strikethrooRoot: path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo"), + taskId: Number(validTaskId) + }); + emit(route, route.kind === "infrastructure-failure" ? 2 : 0); + } + const handoff = decodeHandoff(handoffArg); + const executionConfiguration = loadHarnessConfiguration( + path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo") + ); + if (executionConfiguration.kind === "invalid") { + return emit( + { + kind: "infrastructure-failure", + detail: `Harness invocation configuration is invalid: ${executionConfiguration.errors.join( + " " + )}` + }, + 2 + ); + } + const routed = { + harness: handoff.harness, + cliArgs: executionConfiguration.config[handoff.harness].cliArgs, + model: handoff.model, + ...handoff.reasoningEffort === void 0 ? {} : { reasoningEffort: handoff.reasoningEffort }, + workspace: path7.resolve(validWorkspace), + planId: validPlanId, + taskId: validTaskId, + taskFile: taskPath, + taskMarkdown + }; + const result = await dispatchExternalTask(routed); + emit( + result, + result.kind === "infrastructure-failure" ? 2 : result.kind === "launched-failure" ? 1 : 0 + ); +}; +main().catch((error) => { + emit( + { + kind: "infrastructure-failure", + detail: `Task dispatch infrastructure failed: ${errorMessage2(error)}` + }, + 2 + ); +}); +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + resolveDispatchRoute +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs b/.agents/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-execute-task/SKILL.md b/.agents/skills/st-execute-task/SKILL.md new file mode 100644 index 0000000..558dab5 --- /dev/null +++ b/.agents/skills/st-execute-task/SKILL.md @@ -0,0 +1,154 @@ +--- +name: st-execute-task +description: Use when the user asks to run, execute, or implement one specific task ID within a Strikethroo plan in this repository — triggers include execute task, run task, implement task, do task N. Do not use to execute a whole plan or blueprint, to generate tasks, or for generic development outside Strikethroo. +--- + +# st-execute-task + +## Critical Rules + +1. **Maintain status integrity** — update task status throughout the execution lifecycle. +2. **Document execution** — record all outcomes and issues encountered. + +## Inputs + +The user supplies the numeric plan ID and task ID conversationally. + +## Operating Procedure + +### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +### 2. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, stop and ask the user to confirm the plan ID. +Do not guess a different ID. + +Run `scripts/validate-plan-blueprint.cjs planDir` and treat the +printed path as ``. + +### 3. Validate the task file + +Look for `/tasks/--*.md`, then for the zero-padded +`/tasks/0--*.md`. If neither matches, list the files in +`/tasks/` and stop. Treat the match as ``. + +### 4. Check task status + +Read `status` from the `` frontmatter. + +- `completed`, `in-progress`, or `needs-clarification`: stop, and name the way + out (re-execute a completed task through execute-blueprint, answer the open + clarification questions first). +- `pending` or `failed`: execute. +- Missing or unrecognized: proceed with caution and note the ambiguity. + +### 5. Validate dependencies + +Run `scripts/check-task-dependencies.cjs `. If it exits 1, +stop and report that unresolved dependencies block the task. Do not proceed +until they are satisfied. + +### 6. Agent selection + +Read `/config/hooks/PRE_TASK_ASSIGNMENT.md` and follow its instructions +for selecting the appropriate agent or skill set for this task. + +### 7. Update status to in-progress + +Rewrite the YAML frontmatter of ``, setting `status: "in-progress"`. +Preserve all other frontmatter fields exactly. + +### 8. Execute the task + +Resolve the route before deploying any agent; resolution launches no task +work: + +```text +scripts/dispatch-task-execution.cjs resolve +``` + +External execution uses: + +```text +scripts/dispatch-task-execution.cjs execute +``` + +`` is the exact supported harness identifier running this +skill; `` is the project working directory. + +Interpret the one-line JSON result and act on its `kind` exactly once: + +| `kind` | Required action | +| --- | --- | +| `native-default` | Dispatch natively with no execution-setting prose. | +| `native-override` | Dispatch natively, explicitly requiring the exact returned `model`. Require the returned `reasoningEffort` only when that property is present. | +| `external-override` | Run the `execute` command with the returned `handoff`, then read its result against this same table. | +| `fallback` | Nothing launched. Record the returned `reason` and `detail` visibly, then dispatch natively with no execution-setting prose. | +| `launched-success` | The external process exited zero. Do not dispatch natively; review status and evidence as you would for a native agent. | +| `launched-failure` | A failed task. Set its status to `failed` and run `/config/hooks/POST_ERROR_DETECTION.md`. Never retry it natively. | +| `infrastructure-failure` | Handle exactly as the preceding row. | + +Handoff rules: + +- Pass the exact opaque `handoff` string the resolver returned for that task. Never reconstruct one. +- Never reuse a handoff for another task, and never rerun resolution after launches begin. + +Steps 9–11 are this skill's failed-status and error-hook path. + +For a native dispatch, deploy an agent using your internal Task tool. The agent +must read and execute `/config/hooks/PRE_TASK_EXECUTION.md` before any +implementation work, then read the complete `` and implement it. +Do not run `scripts/check-for-updates.cjs`; delegated workers do not consume update notices. + +### 9. Update status to completed or failed + +After the agent finishes, rewrite the YAML frontmatter of `` based +on the outcome: + +- Set `status: "completed"` if the task was implemented successfully and + all acceptance criteria are met. +- Set `status: "failed"` if the task could not be completed, acceptance + criteria were not met, or an unrecoverable error occurred. + +Preserve all other frontmatter fields exactly. + +### 10. Document noteworthy events + +If anything significant occurred during execution — decisions made, issues +encountered, deviations from the plan, or follow-up actions required — +append a "Noteworthy Events" section to the end of ``: + +```markdown +## Noteworthy Events +- [YYYY-MM-DD] [Event description with sufficient context for the orchestrator] +``` + +### 11. Error handling + +If any error occurred during execution, read +`/config/hooks/POST_ERROR_DETECTION.md` and execute its instructions. +Document the error in Noteworthy Events and ensure the task status is set to +`failed` if it is not already. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. + +## Failure Modes + +- **Execution errors.** If a task fails, read `/config/hooks/POST_ERROR_DETECTION.md`, document the error in Noteworthy Events, and ensure the task status is set to `failed`. diff --git a/.agents/skills/st-execute-task/scripts/check-for-updates.cjs b/.agents/skills/st-execute-task/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-execute-task/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-execute-task/scripts/check-task-dependencies.cjs b/.agents/skills/st-execute-task/scripts/check-task-dependencies.cjs new file mode 100644 index 0000000..e1239e5 --- /dev/null +++ b/.agents/skills/st-execute-task/scripts/check-task-dependencies.cjs @@ -0,0 +1,3042 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/check-task-dependencies.ts +var check_task_dependencies_exports = {}; +__export(check_task_dependencies_exports, { + _main: () => _main +}); +module.exports = __toCommonJS(check_task_dependencies_exports); +var fs5 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/task-file.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/task-file.ts +var findTaskFile = (planDir, taskId) => { + const taskDir = path4.join(planDir, "tasks"); + if (!fs4.existsSync(taskDir)) return null; + const idStr = String(taskId); + const variations = [idStr, idStr.padStart(2, "0"), idStr.replace(/^0+/, "") || "0"]; + const uniqueVariations = [...new Set(variations)]; + try { + const files = fs4.readdirSync(taskDir); + return uniqueVariations.reduce((acc, v) => { + if (acc) return acc; + const match = files.find((f) => f.startsWith(`${v}--`) && f.endsWith(".md")); + return match ? path4.join(taskDir, match) : null; + }, null) ?? null; + } catch (_err) { + return null; + } +}; +var TASK_STATUSES = [ + "pending", + "in-progress", + "completed", + "needs-clarification", + "failed" +]; +var MAX_VALUE_PREVIEW = 80; +var describeValue = (value) => { + let text = ""; + const ancestors = []; + const full = () => text.length > MAX_VALUE_PREVIEW; + const write = (node) => { + if (full()) return; + if (typeof node !== "object" || node === null || node instanceof Date) { + text += JSON.stringify(node) ?? String(node); + return; + } + if (ancestors.includes(node)) { + text += '"[Circular]"'; + return; + } + ancestors.push(node); + if (Array.isArray(node)) { + text += "["; + for (let i = 0; i < node.length && !full(); i++) { + if (i > 0) text += ","; + write(node[i] ?? null); + } + text += "]"; + } else { + text += "{"; + let first = true; + for (const [key, item] of Object.entries(node)) { + if (full()) break; + text += `${first ? "" : ","}${JSON.stringify(key)}:`; + first = false; + write(item); + } + text += "}"; + } + ancestors.pop(); + }; + try { + write(value); + } catch { + text = String(value); + } + return text.length > MAX_VALUE_PREVIEW ? `${text.slice(0, MAX_VALUE_PREVIEW)}\u2026` : text; +}; +var isTaskStatus = (value) => typeof value === "string" && TASK_STATUSES.includes(value); +var toTaskId = (value) => { + if (typeof value === "number") return Number.isSafeInteger(value) && value >= 0 ? value : null; + if (typeof value === "string" && /^[0-9]+$/.test(value)) { + const id = Number(value); + return Number.isSafeInteger(id) ? id : null; + } + return null; +}; +var readDependencies = (value) => { + if (value === void 0 || value === null) return []; + if (!Array.isArray(value)) return null; + const ids = []; + for (const item of value) { + const id = toTaskId(item); + if (id === null) return null; + ids.push(id); + } + return ids; +}; +var readTaskMetadata = (markdown) => { + const frontmatter = readYamlFrontmatter(markdown); + if (frontmatter.kind === "none") { + return { kind: "rejected", reason: "task frontmatter not found" }; + } + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + const { status, dependencies } = frontmatter.data; + const expected = TASK_STATUSES.join(", "); + if (status === void 0) { + return { kind: "rejected", reason: `status is missing; expected one of ${expected}` }; + } + if (!isTaskStatus(status)) { + return { + kind: "rejected", + reason: `status ${describeValue(status)} is not one of ${expected}` + }; + } + const ids = readDependencies(dependencies); + if (ids === null) { + return { + kind: "rejected", + reason: `dependencies must be a list of integer task ids; got ${describeValue(dependencies)}` + }; + } + return { kind: "metadata", metadata: { status, dependencies: ids } }; +}; +var readDocument2 = (file) => { + try { + return fs4.readFileSync(file, "utf8"); + } catch (_err) { + return null; + } +}; +var collectTaskReadinessIssues = (planDir, taskId) => { + const idLabel = String(taskId); + const issue = (kind, detail) => ({ + taskId: idLabel, + kind, + detail + }); + const taskFile = findTaskFile(planDir, taskId); + if (!taskFile) return [issue("missing", "task file not found")]; + const taskContent = readDocument2(taskFile); + if (taskContent === null) return [issue("invalid-metadata", "task file could not be read")]; + const task = readTaskMetadata(taskContent); + if (task.kind === "rejected") return [issue("invalid-metadata", task.reason)]; + const issues = []; + if (task.metadata.status === "needs-clarification") { + issues.push(issue("needs-clarification", "status is needs-clarification")); + } + for (const depId of task.metadata.dependencies) { + const depFile = findTaskFile(planDir, depId); + if (!depFile) { + issues.push(issue("unresolved-dependency", `dependency ${depId} not found`)); + continue; + } + const depContent = readDocument2(depFile); + if (depContent === null) { + issues.push(issue("unresolved-dependency", `dependency ${depId} could not be read`)); + continue; + } + const dep = readTaskMetadata(depContent); + if (dep.kind === "rejected") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} has invalid metadata: ${dep.reason}`) + ); + continue; + } + if (dep.metadata.status !== "completed") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} status is ${dep.metadata.status}`) + ); + } + } + return issues; +}; + +// src/skill-scripts/check-task-dependencies.ts +var _printError = (message) => { + console.error(`ERROR: ${message}`); +}; +var _printSuccess = (message) => { + console.log(`\u2713 ${message}`); +}; +var _printWarning = (message) => { + console.log(`\u26A0 ${message}`); +}; +var _printInfo = (message) => { + console.log(message); +}; +var _main = (startPath = process.cwd()) => { + if (process.argv.length !== 4) { + _printError("Invalid number of arguments"); + console.log("Usage: node check-task-dependencies.cjs "); + console.log("Example: node check-task-dependencies.cjs 16 03"); + process.exit(1); + } + const inputId = process.argv[2]; + const taskId = process.argv[3]; + if (!inputId || !taskId) { + _printError("Invalid arguments"); + process.exit(1); + } + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + _printError(`Plan "${inputId}" not found or invalid`); + process.exit(1); + } + const { planDir, planId } = resolved; + _printInfo(`Found plan directory: ${planDir}`); + const taskFile = findTaskFile(planDir, taskId); + if (!taskFile) { + _printError(`Task with ID ${taskId} not found in plan ${planId}`); + process.exit(1); + } + _printInfo(`Checking task: ${path5.basename(taskFile)}`); + console.log(""); + const issues = collectTaskReadinessIssues(planDir, taskId); + const dependencyIssues = issues.filter((issue) => issue.kind === "unresolved-dependency"); + const blockingIssues = issues.filter((issue) => issue.kind !== "unresolved-dependency"); + if (blockingIssues.length > 0) { + for (const issue of blockingIssues) { + _printError(issue.detail); + } + process.exit(1); + } + const metadata = readTaskMetadata(fs5.readFileSync(taskFile, "utf8")); + if (metadata.kind === "rejected") { + _printError(metadata.reason); + process.exit(1); + } + const dependencies = metadata.metadata.dependencies; + if (dependencies.length === 0) { + _printSuccess("Task has no dependencies - ready to execute!"); + process.exit(0); + } + _printInfo("Task dependencies found:"); + dependencies.forEach((dep) => { + console.log(` - Task ${dep}`); + }); + console.log(""); + _printInfo("Checking dependency status..."); + console.log(""); + let resolvedCount = 0; + for (const depId of dependencies) { + const depFile = findTaskFile(planDir, depId); + const depMetadata = depFile ? readTaskMetadata(fs5.readFileSync(depFile, "utf8")) : null; + const depStatus = depMetadata?.kind === "metadata" ? depMetadata.metadata.status : null; + if (depStatus === "completed") { + _printSuccess(`Task ${depId} - Status: completed \u2713`); + resolvedCount++; + } else { + _printWarning(`Task ${depId} - Status: ${depStatus ?? "unknown"} \u2717`); + } + } + console.log(""); + _printInfo("========================================="); + _printInfo("Dependency Check Summary"); + _printInfo("========================================="); + _printInfo(`Total dependencies: ${dependencies.length}`); + _printInfo(`Resolved: ${resolvedCount}`); + _printInfo(`Unresolved: ${dependencies.length - resolvedCount}`); + console.log(""); + if (dependencyIssues.length === 0) { + _printSuccess(`All dependencies are resolved! Task ${taskId} is ready to execute.`); + process.exit(0); + } + _printError(`Task ${taskId} has unresolved dependencies:`); + dependencyIssues.forEach((issue) => { + console.log(issue.detail); + }); + _printInfo("Please complete the dependencies before executing this task."); + process.exit(1); +}; +if (require.main === module) { + _main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-execute-task/scripts/dispatch-task-execution.cjs b/.agents/skills/st-execute-task/scripts/dispatch-task-execution.cjs new file mode 100755 index 0000000..14ea3e5 --- /dev/null +++ b/.agents/skills/st-execute-task/scripts/dispatch-task-execution.cjs @@ -0,0 +1,3688 @@ +#!/usr/bin/env node +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/dispatch-task-execution.ts +var dispatch_task_execution_exports = {}; +__export(dispatch_task_execution_exports, { + resolveDispatchRoute: () => resolveDispatchRoute +}); +module.exports = __toCommonJS(dispatch_task_execution_exports); +var fs5 = __toESM(require("fs")); +var path7 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/dispatch-target-selector.ts +var path = __toESM(require("path")); +var import_child_process = require("child_process"); +var executionTargetId = (target) => JSON.stringify([target.model, target.harness ?? null, target.reasoning_effort ?? null]); +var runSelector = (scriptPath, input, timeoutMs) => { + try { + const nodeScript = /\.(?:cjs|mjs|js)$/.test(scriptPath); + const stdout = nodeScript ? (0, import_child_process.execFileSync)(process.execPath, [scriptPath], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }) : (0, import_child_process.execFileSync)(scriptPath, [], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }); + return { ok: true, stdout }; + } catch { + return { ok: false }; + } +}; +var nativeDefault = (reason, detail) => ({ kind: "native-default", reason, detail }); +var resolveRepositoryScript = (projectRoot, configured) => { + if (path.isAbsolute(configured)) return null; + const root = path.resolve(projectRoot); + const resolved = path.resolve(root, configured); + return resolved === root || resolved.startsWith(`${root}${path.sep}`) ? resolved : null; +}; +var selectDispatchTarget = (config, profileName, avoidedIds, options) => { + const profile = config.profiles.find((candidate) => candidate.name === profileName); + if (!profile) { + return nativeDefault( + "profile-unavailable", + `Execution profile "${profileName}" is not present in current configuration.` + ); + } + const candidates = profile.targets.filter( + (target) => config.allowExternalHarnessExecution || target.harness === void 0 || target.harness === options.currentHarness + ).map((target) => ({ id: executionTargetId(target), target })); + if (candidates.length === 0) { + return nativeDefault( + "targets-exhausted", + `Execution profile "${profileName}" has no targets for the current harness while external harness execution is disabled.` + ); + } + const available = candidates.filter((candidate) => !avoidedIds.has(candidate.id)); + if (available.length === 0) { + return nativeDefault( + "targets-exhausted", + `All ${candidates.length} configured target(s) for profile "${profileName}" were avoided.` + ); + } + if (config.resolverScript === void 0) { + const selected2 = available[0]; + return { kind: "selected", ...selected2, source: "built-in" }; + } + const scriptPath = resolveRepositoryScript(options.projectRoot, config.resolverScript); + if (!scriptPath) { + return nativeDefault( + "selector-failure", + "Custom target selector path is not repository-relative." + ); + } + const input = { + version: 1, + task: { id: options.taskId, profile: profileName }, + candidates, + avoid: [...avoidedIds].sort() + }; + const result = (options.runSelector ?? runSelector)( + scriptPath, + JSON.stringify(input), + options.timeoutMs ?? 1e4 + ); + if (!result.ok || result.stdout === void 0) { + return nativeDefault( + "selector-failure", + "Custom target selector did not complete successfully." + ); + } + let output; + try { + output = JSON.parse(result.stdout); + } catch { + return nativeDefault("selector-failure", "Custom target selector returned invalid JSON."); + } + if (typeof output !== "object" || output === null || Array.isArray(output) || Object.keys(output).length !== 1 || typeof output.target !== "string") { + return nativeDefault("selector-failure", "Custom target selector returned an invalid result."); + } + const selectedId = output.target; + const selected = candidates.find((candidate) => candidate.id === selectedId); + if (!selected || avoidedIds.has(selected.id)) { + return nativeDefault( + "selector-failure", + "Custom target selector returned an unknown or avoided target." + ); + } + return { kind: "selected", ...selected, source: "custom" }; +}; + +// src/skill-scripts/shared/external-dispatch.ts +var path3 = __toESM(require("path")); +var import_child_process2 = require("child_process"); + +// src/skill-scripts/shared/executable-resolution.ts +var fs = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var DEFAULT_PATHEXT = ".EXE;.CMD;.BAT;.COM"; +var hasPathSeparator = (executable) => /[\\/]/.test(executable); +var resolveExecutablePath = (executable, environment = {}) => { + const env = environment.env ?? process.env; + const platform = environment.platform ?? process.platform; + const win32 = platform === "win32"; + const suffixes = win32 ? ["", ...(env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean)] : [""]; + const directories = hasPathSeparator(executable) ? [""] : (env.PATH ?? "").split(path2.delimiter).filter(Boolean); + const mode = win32 ? fs.constants.F_OK : fs.constants.X_OK; + for (const directory of directories) { + for (const suffix of suffixes) { + const candidate = path2.resolve(directory, `${executable}${suffix}`); + try { + fs.accessSync(candidate, mode); + if (fs.statSync(candidate).isFile()) return fs.realpathSync(candidate); + } catch { + } + } + } + return null; +}; +var executableResolves = (executable, environment) => resolveExecutablePath(executable, environment) !== null; + +// src/skill-scripts/shared/external-dispatch.ts +var taskPrompt = (request) => `Strikethroo external task dispatch \u2014 Plan ${request.planId}, Task ${request.taskId}. +Workspace: ${request.workspace} +Task file: ${request.taskFile} +You are a delegated execution worker. Do not run check-for-updates.cjs or emit update notices. +Before implementation, read and execute ${path3.join( + request.workspace, + ".ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md" +)}. Halt if that hook fails. + +Read and implement this task. Preserve dependency validation, status transitions, evidence reporting, and error-hook handling. Report failures clearly. + +${request.taskMarkdown}`; +var command = (executable, argv, request) => ({ + executable, + argv, + cwd: request.workspace, + stdin: request.prompt +}); +var modelArgv = (model) => model === void 0 ? [] : ["--model", model]; +var EXTERNAL_HARNESS_ADAPTERS = { + claude: { + executable: "claude", + buildCommand: (request) => command( + "claude", + [ + "-p", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--effort", request.reasoningEffort] + ], + request + ), + authenticationArgv: () => ["auth", "status"] + }, + codex: { + executable: "codex", + buildCommand: (request) => command( + "codex", + [ + "exec", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--config", `model_reasoning_effort=${request.reasoningEffort}`], + "-" + ], + request + ), + authenticationArgv: () => ["login", "status"] + }, + cursor: { + executable: "cursor-agent", + buildCommand: (request) => command( + "cursor-agent", + ["--print", ...request.cliArgs, ...modelArgv(request.model)], + request + ), + authenticationArgv: () => ["status"] + }, + gemini: { + executable: "gemini", + // The empty positional prompt is the existing contract — content travels on + // stdin. It stays even when the model pair is dropped. + buildCommand: (request) => command("gemini", ["--prompt", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + copilot: { + executable: "copilot", + buildCommand: (request) => command("copilot", ["-p", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + opencode: { + executable: "opencode", + buildCommand: (request) => command( + "opencode", + [ + "run", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--variant", request.reasoningEffort], + "-" + ], + request + ), + authenticationArgv: () => ["auth", "list"] + } +}; +var adapterKeys = Object.keys(EXTERNAL_HARNESS_ADAPTERS).sort(); +var harnessKeys = [...SUPPORTED_HARNESSES].sort(); +if (adapterKeys.join("\0") !== harnessKeys.join("\0")) { + throw new Error("External harness adapter registry does not cover SUPPORTED_HARNESSES exactly."); +} +var taskCommandRequest = (request) => ({ + cliArgs: request.cliArgs ?? [], + model: request.model, + reasoningEffort: request.reasoningEffort, + workspace: request.workspace, + prompt: taskPrompt(request) +}); +var CAPTURED_STDOUT_LIMIT = 262144; +var AUTHENTICATION_TIMEOUT_MS = 3e4; +var STDIO_SLOTS = { + ignore: { stdout: "ignore" }, + inherit: { stdout: "inherit" }, + capture: { stdout: "pipe" } +}; +var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore", timeoutMs) => new Promise((resolve4, reject) => { + let settled = false; + const child = (0, import_child_process2.spawn)(executable, argv, { + cwd, + shell: false, + stdio: [ + stdin === void 0 ? "ignore" : "pipe", + STDIO_SLOTS[outputMode].stdout, + outputMode === "ignore" ? "ignore" : "inherit" + ] + }); + const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => { + if (settled) return; + settled = true; + child.kill("SIGKILL"); + resolve4({ exitCode: 1, timedOut: true }); + }, timeoutMs); + const settle = (outcome2) => { + if (settled) return; + settled = true; + clearTimeout(timer); + resolve4(outcome2); + }; + const fail = (error) => { + if (settled) return; + settled = true; + clearTimeout(timer); + reject(error); + }; + let captured = ""; + if (outputMode === "capture") { + child.stdout.setEncoding("utf8"); + child.stdout.once("error", fail); + child.stdout.on("data", (chunk) => { + process.stderr.write(chunk); + captured += chunk; + if (captured.length > CAPTURED_STDOUT_LIMIT) { + captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT); + } + }); + } + child.once("error", fail); + child.once("close", (code) => { + settle({ + exitCode: code ?? 1, + ...outputMode === "capture" ? { stdout: captured } : {} + }); + }); + if (stdin !== void 0) { + child.stdin.once("error", fail); + try { + child.stdin.end(stdin); + } catch (error) { + fail(error instanceof Error ? error : new Error(String(error))); + } + } +}); +var authenticateHarness = async (commandSpec, adapter, timeoutMs = AUTHENTICATION_TIMEOUT_MS) => { + const executable = commandSpec.executable; + try { + const result = await runProcess( + executable, + adapter.authenticationArgv(), + commandSpec.cwd, + void 0, + "ignore", + timeoutMs + ); + if (result.timedOut === true) { + return { + ok: false, + detail: `${executable} authentication check timed out after ${timeoutMs} ms and was terminated.` + }; + } + return result.exitCode === 0 ? { ok: true } : { + ok: false, + detail: `${executable} authentication check failed: exited ${result.exitCode}.` + }; + } catch (error) { + const code = error.code; + return { + ok: false, + detail: `${executable} authentication check could not launch${code === void 0 ? "" : ` (${code})`}: ${errorMessage(error)}` + }; + } +}; +var dependencies = { + executableExists: executableResolves, + authenticate: authenticateHarness, + launch: (commandSpec, options) => runProcess( + commandSpec.executable, + commandSpec.argv, + commandSpec.cwd, + commandSpec.stdin, + options?.captureStdout === true ? "capture" : "inherit" + ) +}; +var errorMessage = (error) => error instanceof Error ? error.message : String(error); +var prepareLaunch = async (harness, input, active, guard) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + if (!adapter) { + return { + kind: "fallback", + reason: "adapter-unavailable", + detail: `No adapter is registered for ${harness}.` + }; + } + const blocked = guard?.(); + if (blocked) return blocked; + const executable = adapter.executable; + if (!active.executableExists(executable)) { + return { + kind: "fallback", + reason: "executable-unavailable", + detail: `${executable} is unavailable.` + }; + } + const commandSpec = adapter.buildCommand(input); + const authentication = await active.authenticate(commandSpec, adapter); + if (!authentication.ok) { + return { + kind: "fallback", + reason: "authentication-failed", + detail: authentication.detail ?? `${adapter.executable} authentication check failed.` + }; + } + return { kind: "ready", command: commandSpec }; +}; +var launchPrepared = async (prepared, active, label, captureStdout = false) => { + if (prepared.kind === "fallback") return prepared; + try { + const launched = await active.launch(prepared.command, { captureStdout }); + const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout }; + return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout }; + } catch (error) { + return { + kind: "infrastructure-failure", + detail: `External ${label} process failed: ${errorMessage(error)}` + }; + } +}; +var unsupportedReasoningEffort = (request) => request.reasoningEffort !== void 0 && (request.harness === "cursor" || request.harness === "gemini" || request.harness === "copilot") ? { + kind: "fallback", + reason: "unsupported-reasoning-effort", + detail: `${request.harness} does not support a generic reasoning_effort override.` +} : void 0; +var dispatchExternalTask = async (request, overrides = {}) => { + const active = { ...dependencies, ...overrides }; + const prepared = await prepareLaunch( + request.harness, + taskCommandRequest(request), + active, + () => unsupportedReasoningEffort(request) + ); + return launchPrepared(prepared, active, "task"); +}; + +// src/skill-scripts/shared/harness-availability.ts +var import_crypto2 = require("crypto"); +var import_child_process3 = require("child_process"); +var fs4 = __toESM(require("fs")); +var os = __toESM(require("os")); +var path6 = __toESM(require("path")); + +// src/skill-scripts/shared/harness-configuration.ts +var import_crypto = require("crypto"); +var fs3 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/execution-routing.ts +var fs2 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); +var EXECUTION_ROUTING_SECTION = "execution_routing"; +var isPlainObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0; +var validateTarget = (profileName, index, raw, supportedHarnesses, errors) => { + const label = `profile "${profileName}" models[${index}]`; + if (!isPlainObject3(raw)) { + errors.push(`${label} must be a mapping with an exact "model" string.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "model" && key !== "harness" && key !== "reasoning_effort") { + errors.push(`${label} has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.model)) { + errors.push(`${label} requires a non-empty exact "model" string.`); + return null; + } + const target = { model: raw.model }; + if ("harness" in raw) { + if (!isNonEmptyString(raw.harness)) { + errors.push(`${label} "harness" must be a non-empty string when provided.`); + return null; + } + if (!supportedHarnesses.includes(raw.harness)) { + errors.push(`${label} harness "${raw.harness}" is not a supported harness.`); + return null; + } + target.harness = raw.harness; + } + if ("reasoning_effort" in raw) { + if (!isNonEmptyString(raw.reasoning_effort)) { + errors.push(`${label} "reasoning_effort" must be a non-empty string when provided.`); + return null; + } + target.reasoning_effort = raw.reasoning_effort; + } + return target; +}; +var validateProfile = (name, raw, supportedHarnesses, errors) => { + if (!isPlainObject3(raw)) { + errors.push(`profile "${name}" must be a mapping with "description" and "models".`); + return null; + } + if ("resolver" in raw) { + errors.push( + `profile "${name}" configures a per-profile resolver; only the single top-level "resolver" is supported.` + ); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "description" && key !== "models") { + errors.push(`profile "${name}" has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.description)) { + errors.push(`profile "${name}" requires a non-empty LLM-facing "description".`); + return null; + } + if (!Array.isArray(raw.models) || raw.models.length === 0) { + errors.push(`profile "${name}" requires a non-empty ordered "models" array.`); + return null; + } + const targets = []; + for (let i = 0; i < raw.models.length; i += 1) { + const target = validateTarget(name, i, raw.models[i], supportedHarnesses, errors); + if (!target) return null; + targets.push(target); + } + return { name, description: raw.description.trim(), targets }; +}; +var loadRoutingConfig = (strikethrooRoot, supportedHarnesses) => { + const configPath = path4.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs2.readFileSync(configPath, "utf8"); + } catch { + return { kind: "no-config" }; + } + if (!hasYamlContent(contents)) return { kind: "disabled" }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) return { kind: "disabled" }; + if (!isPlainObject3(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[EXECUTION_ROUTING_SECTION]; + if (section === null || section === void 0) return { kind: "disabled" }; + const errors = []; + if (!isPlainObject3(section)) { + return { + kind: "invalid", + errors: [`config.yaml "${EXECUTION_ROUTING_SECTION}" must be a YAML mapping.`] + }; + } + for (const key of Object.keys(section)) { + if (key !== "enabled" && key !== "allow_external_harness_execution" && key !== "profiles" && key !== "resolver") { + errors.push(`${EXECUTION_ROUTING_SECTION} has unknown key "${key}".`); + } + } + if ("allow_external_harness_execution" in section && typeof section.allow_external_harness_execution !== "boolean") { + errors.push( + `${EXECUTION_ROUTING_SECTION} "allow_external_harness_execution" must be true or false.` + ); + } + if ("enabled" in section) { + if (typeof section.enabled !== "boolean") { + errors.push(`${EXECUTION_ROUTING_SECTION} "enabled" must be true or false.`); + return { kind: "invalid", errors }; + } + if (!section.enabled) + return errors.length > 0 ? { kind: "invalid", errors } : { kind: "disabled" }; + } + const rawProfiles = "profiles" in section && section.profiles == null ? {} : section.profiles; + if (!("profiles" in section) || !isPlainObject3(rawProfiles)) { + errors.push(`${EXECUTION_ROUTING_SECTION} requires a "profiles" mapping.`); + return { kind: "invalid", errors }; + } + const profiles = []; + for (const [name, rawProfile] of Object.entries(rawProfiles)) { + const profile = validateProfile(name, rawProfile, supportedHarnesses, errors); + if (profile) profiles.push(profile); + } + let resolverScript; + if ("resolver" in section) { + const resolver = section.resolver; + if (!isPlainObject3(resolver) || !isNonEmptyString(resolver.script)) { + errors.push('resolver must be a mapping with a non-empty "script" path.'); + } else { + for (const key of Object.keys(resolver)) { + if (key !== "script") errors.push(`resolver has unknown key "${key}".`); + } + resolverScript = resolver.script; + } + } + if (errors.length > 0) return { kind: "invalid", errors }; + if (profiles.length === 0) return { kind: "disabled" }; + const config = { + allowExternalHarnessExecution: section.allow_external_harness_execution === true, + profiles + }; + if (resolverScript !== void 0) config.resolverScript = resolverScript; + return { kind: "config", config }; +}; + +// src/skill-scripts/shared/harness-configuration.ts +var HARNESS_CONFIGURATION_SECTION = "harnesses"; +var HARNESS_CONFIGURATION_NORMALIZATION_VERSION = 1; +var isPlainObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var hashHarnessCliArgs = (harness, cliArgs, normalizationVersion = HARNESS_CONFIGURATION_NORMALIZATION_VERSION) => (0, import_crypto.createHash)("sha256").update( + JSON.stringify({ + schema: normalizationVersion, + harness, + cliArgs + }), + "utf8" +).digest("hex"); +var normalizeInvocation = (harness, cliArgs) => { + const immutableArgs = Object.freeze([...cliArgs]); + return Object.freeze({ + cliArgs: immutableArgs, + cliArgsHash: hashHarnessCliArgs(harness, immutableArgs) + }); +}; +var emptyConfiguration = () => Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, normalizeInvocation(harness, [])]) + ) +); +var validateHarnessEntry = (harness, raw, errors) => { + const entryPath = `config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness}`; + if (!isPlainObject4(raw)) { + errors.push(`${entryPath} must be a mapping.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "cli_args") errors.push(`${entryPath}.${key} is not supported.`); + } + if (!("cli_args" in raw)) return normalizeInvocation(harness, []); + if (!Array.isArray(raw.cli_args)) { + errors.push(`${entryPath}.cli_args must be an array of exact strings.`); + return null; + } + const cliArgs = []; + raw.cli_args.forEach((value, index) => { + const valuePath = `${entryPath}.cli_args[${index}]`; + if (typeof value !== "string" || value.length === 0) { + errors.push(`${valuePath} must be a non-empty string.`); + return; + } + if (value.includes("\0")) { + errors.push(`${valuePath} must not contain a NUL character.`); + return; + } + cliArgs.push(value); + }); + return normalizeInvocation(harness, cliArgs); +}; +var loadHarnessConfiguration = (strikethrooRoot) => { + const configPath = path5.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs3.readFileSync(configPath, "utf8"); + } catch (error) { + if (error.code === "ENOENT") { + return { kind: "config", config: emptyConfiguration() }; + } + return { + kind: "invalid", + errors: [ + `config.yaml could not be read: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (!hasYamlContent(contents)) return { kind: "config", config: emptyConfiguration() }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[HARNESS_CONFIGURATION_SECTION]; + if (section === null || section === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(section)) { + return { + kind: "invalid", + errors: [`config.yaml ${HARNESS_CONFIGURATION_SECTION} must be a YAML mapping.`] + }; + } + const errors = []; + const supportedHarnesses = new Set(SUPPORTED_HARNESSES); + for (const harness of Object.keys(section)) { + if (!supportedHarnesses.has(harness)) { + errors.push(`config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness} is not supported.`); + } + } + const entries = {}; + for (const harness of SUPPORTED_HARNESSES) { + if (!(harness in section)) { + entries[harness] = normalizeInvocation(harness, []); + continue; + } + const entry = validateHarnessEntry(harness, section[harness], errors); + if (entry) entries[harness] = entry; + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "config", config: Object.freeze(entries) }; +}; + +// src/skill-scripts/shared/harness-availability.ts +var AVAILABILITY_REGISTRY_VERSION = 4; +var AVAILABLE_TTL_MS = 30 * 60 * 1e3; +var UNAVAILABLE_TTL_MS = 5 * 60 * 1e3; +var PROBE_TIMEOUT_MS = 2e4; +var AVAILABILITY_CACHE_RELATIVE_PATH = path6.join("runtime", "harness-availability.json"); +var CACHE_VERSION = 2; +var availabilityDefinition = (harness) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + return { + executable: adapter.executable, + buildCommand: (cwd, cliArgs, prompt) => adapter.buildCommand({ cliArgs, workspace: cwd, prompt }) + }; +}; +var HARNESS_AVAILABILITY_REGISTRY = Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, availabilityDefinition(harness)]) + ) +); +var runProbe = (command2, timeoutMs) => new Promise((resolve4) => { + let stdout = ""; + let stderr = ""; + let settled = false; + let timedOut = false; + const finish = (result) => { + if (settled) return; + settled = true; + resolve4(result); + }; + const child = (0, import_child_process3.spawn)(command2.executable, command2.argv, { + cwd: command2.cwd, + shell: false, + stdio: ["pipe", "pipe", "pipe"] + }); + child.stdout?.setEncoding("utf8"); + child.stderr?.setEncoding("utf8"); + child.stdout?.on("data", (chunk) => { + stdout = (stdout + chunk).slice(-4096); + }); + child.stderr?.on("data", (chunk) => { + stderr = (stderr + chunk).slice(-4096); + }); + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGKILL"); + child.stdout?.destroy(); + child.stderr?.destroy(); + finish({ exitCode: 1, timedOut, stdout, stderr }); + }, timeoutMs); + child.once("error", (error) => { + clearTimeout(timer); + finish({ exitCode: 1, timedOut, stdout, stderr, error: error.message }); + }); + child.once("close", (code) => { + clearTimeout(timer); + finish({ exitCode: code ?? 1, timedOut, stdout, stderr }); + }); + child.stdin?.on("error", () => void 0); + child.stdin?.end(command2.stdin); +}); +var probeFailureReason = (probe) => { + const reason = probe.timedOut ? `Harness readiness check timed out after ${PROBE_TIMEOUT_MS} ms.` : probe.error ? `Harness readiness check could not launch: ${probe.error}` : probe.exitCode !== 0 ? `Harness readiness check exited ${probe.exitCode}.` : "Harness exited 0 but did not create the required readiness file with the expected content."; + const diagnostics = [ + probe.stderr?.trim() ? `stderr: ${probe.stderr.trim().slice(-4096)}` : "", + probe.stdout?.trim() ? `stdout: ${probe.stdout.trim().slice(-4096)}` : "" + ].filter(Boolean); + return [reason, ...diagnostics].join(" "); +}; +var defaultDependencies = { + now: Date.now, + resolveExecutable: resolveExecutablePath, + runProbe +}; +var isHarness = (value) => typeof value === "string" && SUPPORTED_HARNESSES.includes(value); +var isCacheEntry = (value) => { + if (!value || typeof value !== "object") return false; + const entry = value; + return typeof entry.key === "string" && isHarness(entry.harness) && typeof entry.available === "boolean" && typeof entry.observedAt === "number" && Number.isFinite(entry.observedAt) && typeof entry.expiresAt === "number" && Number.isFinite(entry.expiresAt) && typeof entry.reason === "string"; +}; +var emptyCache = () => ({ version: CACHE_VERSION, entries: [] }); +var readCache = (cachePath) => { + try { + const parsed = JSON.parse(fs4.readFileSync(cachePath, "utf8")); + if (!parsed || typeof parsed !== "object") return emptyCache(); + const record = parsed; + if (record.version !== CACHE_VERSION || !Array.isArray(record.entries)) return emptyCache(); + return { version: CACHE_VERSION, entries: record.entries.filter(isCacheEntry) }; + } catch { + return emptyCache(); + } +}; +var writeCache = (cachePath, entry) => { + fs4.mkdirSync(path6.dirname(cachePath), { recursive: true }); + const cache = readCache(cachePath); + const existingIndex = cache.entries.findIndex((candidate) => candidate.key === entry.key); + if (existingIndex === -1) cache.entries.push(entry); + else if (cache.entries[existingIndex].observedAt <= entry.observedAt) { + cache.entries[existingIndex] = entry; + } + const temporary = `${cachePath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.tmp`; + try { + fs4.writeFileSync(temporary, `${JSON.stringify(cache, null, 2)} +`, { mode: 384 }); + fs4.renameSync(temporary, cachePath); + } finally { + try { + fs4.unlinkSync(temporary); + } catch { + } + } +}; +var cacheKey = (harness, executableIdentity, invocation) => (0, import_crypto2.createHash)("sha256").update( + JSON.stringify({ + harness, + executableIdentity, + cliArgsHash: invocation.cliArgsHash, + normalizationVersion: HARNESS_CONFIGURATION_NORMALIZATION_VERSION, + probeRegistryVersion: AVAILABILITY_REGISTRY_VERSION + }) +).digest("hex"); +var readinessEvidence = () => { + const nonce = (0, import_crypto2.randomUUID)(); + return { + file: "strikethroo-readiness.txt", + content: `strikethroo-readiness:${nonce} +` + }; +}; +var readinessPrompt = (evidence) => `Run a shell command that creates ${evidence.file} in the current workspace with the exact UTF-8 content ${JSON.stringify(evidence.content)}. Do not use a file editing tool. +STRIKETHROO_READINESS=${JSON.stringify(evidence)} +`; +var initializeProbeWorkspace = () => { + const workspace = fs4.mkdtempSync(path6.join(os.tmpdir(), "strikethroo-harness-probe-")); + const initialized = (0, import_child_process3.spawnSync)("git", ["init", "--quiet"], { + cwd: workspace, + shell: false, + stdio: "ignore", + timeout: 5e3 + }); + if (initialized.status === 0 && !initialized.error) return workspace; + fs4.rmSync(workspace, { recursive: true, force: true }); + return void 0; +}; +var hasReadinessEvidence = (workspace, evidence) => { + const target = path6.join(workspace, evidence.file); + try { + return fs4.lstatSync(target).isFile() && fs4.readFileSync(target, "utf8") === evidence.content; + } catch { + return false; + } +}; +var outcome = (harness, available, now, reason) => ({ + harness, + available, + observedAt: now, + expiresAt: now + (available ? AVAILABLE_TTL_MS : UNAVAILABLE_TTL_MS), + reason, + source: "probe" +}); +var invocationFor = (request, harness) => { + if (request.invocation) return request.invocation; + const loaded = loadHarnessConfiguration(request.strikethrooRoot); + return loaded.kind === "config" ? loaded.config[harness] : void 0; +}; +var checkHarnessAvailability = async (request, overrides = {}) => { + const active = { ...defaultDependencies, ...overrides }; + const now = active.now(); + if (request.harness === void 0 || request.harness === request.currentHarness) { + return { + harness: request.harness ?? request.currentHarness, + available: true, + observedAt: now, + expiresAt: now, + reason: "Native/current harness targets do not require a probe.", + source: "bypass" + }; + } + const harness = request.harness; + const invocation = invocationFor(request, harness); + if (!invocation) return outcome(harness, false, now, "Harness configuration is invalid."); + const definition = HARNESS_AVAILABILITY_REGISTRY[harness]; + const executableIdentity = active.resolveExecutable(definition.executable); + if (!executableIdentity) + return outcome( + harness, + false, + now, + `Harness executable '${definition.executable}' was not found on PATH.` + ); + const key = cacheKey(harness, executableIdentity, invocation); + const cachePath = path6.join(request.strikethrooRoot, AVAILABILITY_CACHE_RELATIVE_PATH); + const cached = readCache(cachePath).entries.find( + (entry) => entry.key === key && entry.expiresAt > now + ); + if (cached) { + const { key: _key, ...cachedOutcome } = cached; + return { ...cachedOutcome, source: "cache" }; + } + const complete = (result) => { + const { source: _source, ...cacheEntry } = result; + try { + writeCache(cachePath, { key, ...cacheEntry }); + } catch { + } + return result; + }; + const probeWorkspace = initializeProbeWorkspace(); + if (!probeWorkspace) { + return complete( + outcome( + harness, + false, + now, + "Could not initialize the disposable Git workspace for the readiness check." + ) + ); + } + try { + const evidence = readinessEvidence(); + const command2 = definition.buildCommand( + probeWorkspace, + invocation.cliArgs, + readinessPrompt(evidence) + ); + const probe = await active.runProbe( + { ...command2, executable: executableIdentity }, + PROBE_TIMEOUT_MS + ); + const available = probe.exitCode === 0 && !probe.timedOut && hasReadinessEvidence(probeWorkspace, evidence); + return complete( + outcome( + harness, + available, + now, + available ? "Harness readiness verified." : probeFailureReason(probe) + ) + ); + } finally { + fs4.rmSync(probeWorkspace, { recursive: true, force: true }); + } +}; + +// src/skill-scripts/dispatch-task-execution.ts +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var errorMessage2 = (error) => error instanceof Error ? error.message : String(error); +var encodeHandoff = (route) => Buffer.from(JSON.stringify({ version: 1, ...route }), "utf8").toString("base64url"); +var decodeHandoff = (encoded) => { + let raw; + try { + raw = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8")); + } catch { + throw new Error("Resolved execution handoff is not valid encoded JSON."); + } + if (!raw || typeof raw !== "object" || Array.isArray(raw)) { + throw new Error("Resolved execution handoff must be an object."); + } + const value = raw; + const allowed = ["version", "kind", "harness", "model", "reasoningEffort"]; + if (Object.keys(value).some((key) => !allowed.includes(key)) || value.version !== 1 || value.kind !== "external-override" || typeof value.harness !== "string" || !SUPPORTED_HARNESSES.includes(value.harness) || typeof value.model !== "string" || value.model.length === 0 || "reasoningEffort" in value && typeof value.reasoningEffort !== "string") { + throw new Error("Resolved execution handoff has an invalid shape."); + } + return value; +}; +var externalRoute = (harness, model, reasoningEffort) => { + const exact = { + kind: "external-override", + harness, + model, + ...reasoningEffort === void 0 ? {} : { reasoningEffort } + }; + return { ...exact, handoff: encodeHandoff(exact) }; +}; +var readProfile = (taskMarkdown) => { + const frontmatter = readYamlFrontmatter(taskMarkdown); + if (frontmatter.kind === "none") return { kind: "profile" }; + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + if (!Object.prototype.hasOwnProperty.call(frontmatter.data, "execution_profile")) { + return { kind: "profile" }; + } + const profile = frontmatter.data.execution_profile; + if (typeof profile !== "string" || profile.trim() === "") { + return { kind: "rejected", reason: "execution_profile must be a non-empty string." }; + } + return { kind: "profile", profile }; +}; +var resolveDispatchRoute = async (request) => { + const read = readProfile(request.taskMarkdown); + if (read.kind === "rejected") { + return { kind: "infrastructure-failure", detail: `Task metadata rejected: ${read.reason}` }; + } + const profile = read.profile; + if (profile === void 0) return { kind: "native-default" }; + const configResult = loadRoutingConfig(request.strikethrooRoot, SUPPORTED_HARNESSES); + if (configResult.kind !== "config") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: configResult.kind === "invalid" ? `Execution routing configuration is invalid: ${configResult.errors.join(" ")}` : `Execution profile "${profile}" cannot be resolved because routing is disabled.` + }; + } + const avoided = /* @__PURE__ */ new Set(); + const unavailable = []; + let harnessConfiguration; + const candidateCount = configResult.config.profiles.find((candidate) => candidate.name === profile)?.targets.length ?? 0; + for (let attempt = 0; attempt < Math.max(1, candidateCount); attempt += 1) { + const selection = selectDispatchTarget(configResult.config, profile, avoided, { + currentHarness: request.currentHarness, + projectRoot: request.workspace, + taskId: request.taskId + }); + if (selection.kind === "native-default") { + return { kind: "fallback", reason: selection.reason, detail: selection.detail }; + } + const harness = selection.target.harness; + if (harness === void 0 || harness === request.currentHarness) { + return { + kind: "native-override", + model: selection.target.model, + ...selection.target.reasoning_effort === void 0 ? {} : { reasoningEffort: selection.target.reasoning_effort } + }; + } + harnessConfiguration ??= loadHarnessConfiguration(request.strikethrooRoot); + if (harnessConfiguration.kind === "invalid") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: `Harness invocation configuration is invalid: ${harnessConfiguration.errors.join( + " " + )}` + }; + } + const invocation = harnessConfiguration.config[harness]; + const availability = await checkHarnessAvailability({ + strikethrooRoot: request.strikethrooRoot, + workspace: request.workspace, + harness, + currentHarness: request.currentHarness, + invocation + }); + if (availability.available) { + return externalRoute(harness, selection.target.model, selection.target.reasoning_effort); + } + unavailable.push( + `${harness} (${availability.source === "probe" ? "fresh" : availability.source})` + ); + avoided.add(selection.id); + } + return { + kind: "fallback", + reason: "invalid-execution", + detail: `All configured targets for execution profile "${profile}" are unavailable or exhausted.` + (unavailable.length === 0 ? "" : ` Observations: ${unavailable.join("; ")}`) + }; +}; +var main = async () => { + const args = process.argv.slice(2); + const mode = args.shift(); + if (mode !== "resolve" && mode !== "execute" || args.length < (mode === "execute" ? 6 : 5)) { + emit( + { + kind: "infrastructure-failure", + detail: "Usage: dispatch-task-execution.cjs resolve | execute " + }, + 2 + ); + } + const handoffArg = mode === "execute" ? args.shift() : void 0; + const [taskFile, currentHarnessRaw, workspace, planId, taskId] = args; + if (!taskFile || !currentHarnessRaw || !workspace || !planId || !taskId || !SUPPORTED_HARNESSES.includes(currentHarnessRaw)) { + emit({ kind: "infrastructure-failure", detail: "Task dispatch arguments are invalid." }, 2); + } + const validTaskFile = taskFile; + const validCurrentHarness = currentHarnessRaw; + const validWorkspace = workspace; + const validPlanId = planId; + const validTaskId = taskId; + const taskPath = path7.resolve(validTaskFile); + const taskMarkdown = fs5.readFileSync(taskPath, "utf8"); + if (mode === "resolve") { + const route = await resolveDispatchRoute({ + taskMarkdown, + currentHarness: validCurrentHarness, + workspace: path7.resolve(validWorkspace), + strikethrooRoot: path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo"), + taskId: Number(validTaskId) + }); + emit(route, route.kind === "infrastructure-failure" ? 2 : 0); + } + const handoff = decodeHandoff(handoffArg); + const executionConfiguration = loadHarnessConfiguration( + path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo") + ); + if (executionConfiguration.kind === "invalid") { + return emit( + { + kind: "infrastructure-failure", + detail: `Harness invocation configuration is invalid: ${executionConfiguration.errors.join( + " " + )}` + }, + 2 + ); + } + const routed = { + harness: handoff.harness, + cliArgs: executionConfiguration.config[handoff.harness].cliArgs, + model: handoff.model, + ...handoff.reasoningEffort === void 0 ? {} : { reasoningEffort: handoff.reasoningEffort }, + workspace: path7.resolve(validWorkspace), + planId: validPlanId, + taskId: validTaskId, + taskFile: taskPath, + taskMarkdown + }; + const result = await dispatchExternalTask(routed); + emit( + result, + result.kind === "infrastructure-failure" ? 2 : result.kind === "launched-failure" ? 1 : 0 + ); +}; +main().catch((error) => { + emit( + { + kind: "infrastructure-failure", + detail: `Task dispatch infrastructure failed: ${errorMessage2(error)}` + }, + 2 + ); +}); +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + resolveDispatchRoute +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-execute-task/scripts/find-strikethroo-root.cjs b/.agents/skills/st-execute-task/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-execute-task/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-execute-task/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-execute-task/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-execute-task/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-full-workflow/SKILL.md b/.agents/skills/st-full-workflow/SKILL.md new file mode 100644 index 0000000..c10b4e6 --- /dev/null +++ b/.agents/skills/st-full-workflow/SKILL.md @@ -0,0 +1,473 @@ +--- +name: st-full-workflow +description: Use when the user asks to run the complete end-to-end Strikethroo workflow for a work order in one shot in this repository — triggers include full workflow, end-to-end, plan and execute, do everything, run the whole strikethroo workflow. Do not use when the user wants only one stage (create a plan, generate tasks, or execute a blueprint); use the dedicated skill for that stage instead. +--- + +# st-full-workflow + +## Critical Rule + +Execute all three steps sequentially without waiting for user input between them. + +## Inputs + +The user supplies the work order conversationally. + +## Operating Procedure + +### Step 1: Plan Creation + +#### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +#### 2. Load project context + +Read `/config/STRIKETHROO.md` for this project's directory conventions. +Read `/config/hooks/PRE_PLAN.md` and execute its instructions before +proceeding. Read `/config/templates/PLAN_TEMPLATE.md`; the plan must +conform to it. + +Also read `/config/shared/anti-rationalization.md`. + +#### 3. Analyze the work order + +Identify: + +- Objective. +- Scope and explicit boundaries. +- Success criteria. +- Dependencies, prerequisites, blockers. +- Technical requirements and constraints. + +#### 4. Clarification loop + +If any critical context is missing, ask the user targeted questions. Keep +looping until you have no further questions. Explicitly confirm whether +backwards compatibility is required. Never invent answers; never paper over +a missing answer. + +If the user declines to clarify a blocking question, stop and report the +plan as needing clarification. Do not produce a partial plan. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "I can reasonably assume the answer." | An assumption is not an answer. Ask the question; never invent answers. | +| "Asking again is annoying." | A question the user can decline is recoverable; a silent wrong assumption is not. Ask. | +| "The user implied it, so it's settled." | An implication is not a confirmation. Surface it as a question and get an explicit answer. | + +#### 5. Allocate the next plan ID + +Run `scripts/get-next-plan-id.cjs` for the next available plan ID. Compute its +zero-padded form for the directory name (`{padded-id}--{slug}`) and use the +unpadded integer in the plan frontmatter. + +#### 6. Emit the plan + +Write the plan to +`/plans/{padded-id}--{slug}/plan-{padded-id}--{slug}.md`, conforming to +`/config/templates/PLAN_TEMPLATE.md` in both frontmatter and sections. +Include no time estimates, task lists, or code samples; those belong to the +task-generation step. + +Derive `` from the plan summary: lowercase, alphanumeric and hyphens +only, collapsed, trimmed. + +#### 7. Run post-plan hook + +Execute `/config/hooks/POST_PLAN.md`. + +#### 8. Emit the Step 1 structured summary + +Conclude Step 1 with exactly this block (a retained update notice, when present, follows after the workflow's final summary): + +``` +--- + +Plan Summary: +- Plan ID: [numeric-id] +- Plan File: [absolute-path-to-plan-file] +``` + +Parse the `Plan ID` value from this output and pass it to Step 2. + + + +### Step 2: Task Generation + +Using the plan ID from Step 1: + + + +#### 1. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, surface its stderr to the user and stop the +workflow. +Do not guess a different ID. + +#### 2. Load project context + +Read these files, in order: + +- `/config/STRIKETHROO.md` — project and directory conventions. +- The plan body at the path returned by step 1 — the contract for + what tasks must exist. +- `/config/templates/TASK_TEMPLATE.md` — the schema every task file + must match. +- `/config/shared/anti-rationalization.md` — apply in step 3. + +#### 3. Analyze and decompose the plan + +Read the entire plan. Identify all concrete deliverables **explicitly stated**. +Decompose each deliverable into atomic tasks only when genuinely needed. + +**Task minimization (mandatory):** + +- Create only the minimum number of tasks necessary. Target a 20–30% + reduction from comprehensive lists by questioning the necessity of each + candidate. +- Every task corresponds to an explicit requirement, never a nice-to-have, a + "best practice", or future extensibility the plan does not mention. +- Each task has a unique, non-overlapping purpose. +- Keep error handling inside the task that owns the behavior it guards. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "One extra task won't hurt." | It violates the 20–30% minimization target. Every task traces to an **explicitly stated** deliverable or it does not exist. | +| "This edge case deserves its own task." | Fold it into the task that owns the behavior. Do not split trivially small operations into separate units. | +| "I'll add a test suite to be safe." | Comprehensive tests for trivial functionality are gold-plating. Follow the test philosophy — meaningful tests only. | +| "Future extensibility justifies this task." | YAGNI. The plan does not mention it, so it is not a task. | + +#### 4. Apply granularity and skill rules + +Each task must be: + +- **Single-purpose** — one clear deliverable. +- **Atomic** — cannot be meaningfully split further. +- **Skill-specific** — executable by an agent with 1–2 technical skills. +- **Verifiable** — has explicit acceptance criteria that include at least one + concrete, runnable verification step (a command plus its expected output, or + another observable signal). Never settle for a vague "works correctly". + +Infer skills in kebab-case from the task's technical requirements. Use one +skill for a single-domain task and two for complementary domains, such as +`["api-endpoints", "database"]`. Three or more means the task must be broken +down further. + +#### 5. Test philosophy: "write a few tests, mostly integration" + +**Write tests for:** + +- Custom business logic and algorithms. +- Critical user workflows and data transformations. +- Edge cases and error conditions in core functionality. +- Integration points between components. +- Complex validation or calculation logic. + +**Do not write tests for:** + +- Third-party library and framework functionality. +- Simple CRUD without custom logic. +- Trivial getters/setters and static configuration. +- Obvious functionality that would break immediately if incorrect. + +Combine related test scenarios into one task ("Test user authentication flow", +not separate tasks for login, logout, and validation). Favor integration and +critical-path coverage over per-method unit tests. Never create one test task +per CRUD operation. + +Copy these rules into the "Implementation Notes" of every test task you +generate. + +#### 6. Dependency analysis + +Task B depends on task A when B requires A's output or artifacts, modifies +code created by A, or tests functionality implemented by A. Record it as a +**hard dependency** when B cannot start before A completes and as a **soft +dependency** when B merely runs better after A. Validate that the final +dependency graph is acyclic. + +#### 7. Complexity analysis + +For every candidate task, assign a `complexity_score` (integer 1–10) before +writing any file. Read `references/complexity-rubric.md` before scoring; it +defines the four dimensions each band is judged on. Then apply these rules: + +- Score ≥ 8 → decompose further; do not emit as-is. +- Score 6–7 → sharpen or split; do not emit without an explicit reason. +- Vague acceptance criteria → sharpen them into a concrete, runnable + verification step. +- Trivially small adjacent tasks → merge them. + +**Loop-back rule:** after applying split, sharpen, or merge, re-run dependency +analysis and re-score the adjusted tasks. Repeat no more than three times. If +complexity is still unresolved after three passes, stop and surface the +blocker to the user. + +#### 8. Allocate task IDs + +Run `scripts/get-next-task-id.cjs ` once for the first available task +ID, then allocate the rest by incrementing in-process. Use the unpadded +integer in the task frontmatter `id` field and the zero-padded form in the +filename. The slug derives from a short task title: lowercase, alphanumeric +and hyphens only, collapsed, trimmed. + +#### 9. Emit the task files + +Write each task to: + +``` +/plans//tasks/{padded-id}--{slug}.md +``` + +Each file must conform to `/config/templates/TASK_TEMPLATE.md`. Add +`complexity_notes` only when the score needs justification. Never write +`execution_profile`; the routing helper writes it. + +Fill every body section with task-specific content. Place detailed +implementation guidance inside a `
` block under "Implementation +Notes", written so a non-thinking LLM could execute the task from that +section alone. + +#### 10. Validation checklist + +Before declaring task generation complete, verify: + +- Every **explicitly stated** deliverable in the plan is covered by a task. +- No two tasks overlap in purpose. +- Dependencies form an acyclic graph, with no orphan or circular references. +- Groups are consistent across the plan. +- After writing the task files, run + `scripts/validate-plan-blueprint.cjs complexityScoresValid`. Stop + unless it prints `yes`; if it prints `no`, run + `scripts/validate-plan-blueprint.cjs invalidComplexityTasks` to see + which files are missing, non-integer, or out-of-range, fix them, and re-run. + +#### 11. Route task execution + +Read `/config/hooks/TASK_EXECUTION_ROUTING.md` and follow its +instructions together with this procedure: + +1. Run `scripts/route-task-execution.cjs profiles `. On `no-config` + or `disabled`, routing is off; skip the remaining routing steps and + continue. On `invalid-config`, stop and surface the errors to the user; do + not generate the blueprint. +2. Assign every task in the plan's `tasks/` directory exactly one configured + profile name. Classify the tasks generated in this run from the content + already in your context. If the plan carried task files from an earlier + generation run, read those files to classify them. +3. Write the complete task-ID-to-profile mapping as a JSON object to a + temporary file, for example `{"1": "routine", "2": "demanding"}`. +4. Run `scripts/route-task-execution.cjs apply `. + Target selection happens later at task dispatch, never during generation. +5. On `routed`, delete the temporary mapping file and continue. On any failure + result (`invalid-assignments`, `invalid-tasks`, `routing-failure`, + `infrastructure-failure`), stop and surface the JSON errors to the user. + Never continue to blueprint generation with partially routed tasks. + +Never hand-write a concrete execution target into task frontmatter or task +bodies. + +#### 12. Run the POST_TASK_GENERATION_ALL hook + +Read `/config/hooks/POST_TASK_GENERATION_ALL.md` and follow its +instructions, using `/config/templates/BLUEPRINT_TEMPLATE.md` for the +Execution Blueprint structure. Run the hook only after routing succeeded or +reported routing off. + +### Step 3: Blueprint Execution + +Using the plan ID from Step 1: + + + +#### 1. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, surface its stderr to the user and stop the +workflow. +Do not guess a different ID. + +Run `scripts/validate-plan-blueprint.cjs planDir` and treat the +printed path as ``. + +#### 2. Validate tasks and blueprint existence + +Run `scripts/validate-plan-blueprint.cjs taskCount` and +`scripts/validate-plan-blueprint.cjs blueprintExists`. + +#### 3. Auto-generate tasks and blueprint if missing + +If `taskCount` is 0 or `blueprintExists` is `no`: + +Notify the user: "Tasks or execution blueprint not found. Generating tasks automatically..." + +- Execute the full task generation procedure from Step 2 for this plan ID. +- Re-run the `planFile`, `planDir`, `taskCount`, and `blueprintExists` queries to refresh the resolved paths and counts. + +If the plan still has no tasks or no blueprint, stop and report failure. + +#### 4. Optionally create a feature branch + +Run `scripts/create-feature-branch.cjs ` once before phase execution. A skip is not a failure. Continue on the current branch, and never create the branch by hand. Uncommitted or untracked changes are permitted only inside the repository-root `.ai/strikethroo` subtree. An error result halts execution; report it. + +Then run `scripts/capture-base-commit.cjs ` once to record the commit the review gate diffs against. A `skipped` result continues execution and means the review gate will skip. Only an `error` result halts. + +#### 5. Load project context and execution blueprint + +Read these files, in order: + +- `/config/STRIKETHROO.md` +- The plan document at the path from step 1, including its Execution Blueprint section, which defines the phase groupings and task dispatch order. +- `/config/shared/verification-gate.md` and `/config/shared/anti-rationalization.md`, both applied in the phase loop below. + +#### 6. Execute phases in order + +Use an internal task or todo tracker to monitor progress. For each phase defined in the Execution Blueprint: + +##### 6a. Phase pre-execution +Run `scripts/check-phase-readiness.cjs `. If the script exits non-zero, halt the phase and report the blocking issues before continuing. + +Read `/config/hooks/PRE_PHASE.md` and execute its instructions before starting the phase. + +##### 6b. Task dispatch +Identify all tasks scheduled for this phase whose dependencies are fully satisfied. Read `/config/hooks/PRE_TASK_ASSIGNMENT.md` and follow its instructions for agent selection before dispatching tasks. + +Resolve every selected task's execution route first. Invoke one resolver per selected +task simultaneously in a single parallel tool operation: + +```text +scripts/dispatch-task-execution.cjs resolve +``` + +Resolvers never launch external processes. After interpreting all route results, issue +every external execution and every sub-agent **together in one parallel +tool operation**. External execution uses: + +```text +scripts/dispatch-task-execution.cjs execute +``` + +`` is the exact supported harness identifier running this +skill; `` is the project working directory. + +Interpret the one-line JSON result and act on its `kind` exactly once: + +| `kind` | Required action | +| --- | --- | +| `native-default` | Dispatch natively with no execution-setting prose. | +| `native-override` | Dispatch natively, explicitly requiring the exact returned `model`. Require the returned `reasoningEffort` only when that property is present. | +| `external-override` | Run the `execute` command with the returned `handoff`, then read its result against this same table. | +| `fallback` | Nothing launched. Record the returned `reason` and `detail` visibly, then dispatch natively with no execution-setting prose. | +| `launched-success` | The external process exited zero. Do not dispatch natively; review status and evidence as you would for a native agent. | +| `launched-failure` | A failed task. Set its status to `failed` and run `/config/hooks/POST_ERROR_DETECTION.md`. Never retry it natively. | +| `infrastructure-failure` | Handle exactly as the preceding row. | + +Handoff rules: + +- Pass the exact opaque `handoff` string the resolver returned for that task. Never reconstruct one. +- Never reuse a handoff for another task, and never rerun resolution after launches begin. + +Deploy all remaining native sub-agents simultaneously. Each sub-agent must read and execute `/config/hooks/PRE_TASK_EXECUTION.md` before any implementation work, then execute the task and update its status. Do not run `scripts/check-for-updates.cjs`; delegated workers do not consume update notices. + +##### 6c. Phase completion verification +Ensure every task in the phase has status `completed` and collect its outputs. Do not accept a subagent's report of success as proof. Apply the evidence gate in `/config/shared/verification-gate.md` before marking the phase complete. + +##### 6d. Phase post-execution +Read `/config/hooks/POST_PHASE.md` and execute its instructions. Do not proceed to the next phase until this hook succeeds. + +Update the phase status to `completed` in the plan's Execution Blueprint section. + +Repeat for the next phase until all phases are complete. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "The subagent reported success, so the task is done." | A report is a claim, not evidence. Apply the verification gate before marking the phase complete. | +| "The tests probably pass." | "Probably" is a red flag. Run the proving command, read its output and exit code, then state the result. | +| "I'll verify later, after the next phase." | A phase is not complete until `POST_PHASE.md` succeeds against verified evidence. Verify now; do not advance on an unverified phase. | + +#### 7. Post-execution validation + +Read `/config/hooks/POST_EXECUTION.md` and execute its instructions. If validation fails, halt execution. The plan remains in `plans/` for debugging. + +Before declaring execution complete, apply the evidence gate in `/config/shared/verification-gate.md` to the plan's Success Criteria and Self Validation steps. + +##### Run the code review gate + +After `POST_EXECUTION.md` reports green, follow the `st-code-review` skill and run its bundled mechanism: + +```text +code-review.cjs +``` + +Resolve `code-review.cjs` from the `st-code-review` skill's sibling `scripts` directory and pass the exact supported harness identifier running this skill. If the `st-code-review` skill is not installed, record that outcome in the execution summary and continue to summary and archival. + +Handle the one JSON line it prints on stdout, in this order: + +1. Copy it verbatim into the execution summary's review outcome. Do not reformat it or omit fields. +2. Follow its top-level `action`. If it is `halt`, stop, report the top-level `detail`, and emit the terminal Execution Summary with the review result. If it is `continue`, proceed to the execution summary and archival. +3. Only when `verdict.kind` is `review-recorded`, read `/review/review.xml` and `/review/findings.json`, then decide which findings to act on. `severity` and `confidence` are advisory labels, not instructions. + +Never report an uncertified review as clean. + +Hard rules: + +- The review runs once. Do not re-run the gate to check a fix. +- Detection uses the reviewer route. Dispatch each fix on the implementer route; the reviewer does not fix its findings. +- After any fix, re-run `POST_EXECUTION.md` in full before declaring execution complete. The earlier green result no longer applies. + +#### 8. Append execution summary + +Append an execution summary section to the plan document, filling every field of `/config/templates/EXECUTION_SUMMARY_TEMPLATE.md`. Include a Code Review entry using the result’s `codeReview` field, or Failed with the reason no result was produced. Under Noteworthy Events, always record the review gate's JSON line verbatim, then which findings you acted on versus ignored and why. + +#### 9. Archive the plan + +Move the completed plan directory from `/plans/` to `/archive/`, preserving the entire folder structure. If the move fails, log the error but do not fail the overall execution. + +## Failure Modes + +- **Plan directory already exists for the allocated ID in Step 1.** Re-run the next-plan-id script and retry once. If the conflict persists, stop and report. +- **Execution errors.** If a task fails, read `/config/hooks/POST_ERROR_DETECTION.md`, document the error in Noteworthy Events, halt the phase, and request user direction before continuing. + +## Execution Summary + +Conclude with exactly this block (a retained update notice, when present, follows separately): + +``` +--- +Execution Summary: +- Plan ID: [numeric-id] +- Status: [Archived or Halted] +- Location: [absolute path to current plan directory] +- Code Review: [codeReview from the review result, or Failed with the reason no result was produced] +--- +``` + +Emit this block even when the review gate halts execution. Use the actual status and location; never claim archival after a halt. Copy `codeReview` without dropping the harness, model information, or rejection reasons. Findings acted on do not turn Address into Pass because the review is not re-run. If execution stops before review, report Failed with "Review was not run" and the blocking reason. + +The summary is consumed by downstream automation; keep the format exact. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. diff --git a/.agents/skills/st-full-workflow/references/complexity-rubric.md b/.agents/skills/st-full-workflow/references/complexity-rubric.md new file mode 100644 index 0000000..fee2699 --- /dev/null +++ b/.agents/skills/st-full-workflow/references/complexity-rubric.md @@ -0,0 +1,8 @@ +# Complexity rubric + +| Score | Skill breadth | Acceptance-criteria clarity | Integration surface | Decomposition depth | +| --- | --- | --- | --- | --- | +| 1–3 | One well-known skill | Criteria are concrete and observable | None or a single file/module | No further split possible | +| 4–5 | One primary skill plus a familiar adjacent skill | Criteria are clear with few edge cases | One component or API boundary | Already atomic | +| 6–7 | Two distinct skills, or one skill with ambiguous requirements | Criteria need clarification or have multiple edge cases | Multiple components or contracts | Could still be split | +| 8–10 | Three or more skills, or cross-cutting design decisions | Criteria are vague, unknown, or depend on unresolved choices | Wide integration surface or external systems | Must be decomposed further | diff --git a/.agents/skills/st-full-workflow/scripts/capture-base-commit.cjs b/.agents/skills/st-full-workflow/scripts/capture-base-commit.cjs new file mode 100644 index 0000000..ee434e5 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/capture-base-commit.cjs @@ -0,0 +1,342 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/capture-base-commit.ts +var capture_base_commit_exports = {}; +__export(capture_base_commit_exports, { + _isGitRepo: () => _isGitRepo, + _isValidSha: () => _isValidSha, + _readExistingBaseCommit: () => _readExistingBaseCommit, + main: () => main +}); +module.exports = __toCommonJS(capture_base_commit_exports); +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/git-utils.ts +var import_child_process = require("child_process"); +var GIT_OUTPUT_LIMIT = 64 * 1024 * 1024; +var run = (args, opts) => (0, import_child_process.execFileSync)("git", [...args], { + cwd: opts.cwd, + input: opts.input, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: GIT_OUTPUT_LIMIT +}); +var execGit = (args, opts = {}) => { + try { + const out = run(args, opts); + return opts.trim === false ? out : out.trim(); + } catch { + return null; + } +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/capture-base-commit.ts +var SHA_RE = /^[0-9a-f]{40}$/i; +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var _isGitRepo = () => execGit(["rev-parse", "--is-inside-work-tree"]) === "true"; +var _isValidSha = (value) => typeof value === "string" && SHA_RE.test(value); +var _readExistingBaseCommit = (filePath) => { + let raw; + try { + raw = fs4.readFileSync(filePath, "utf8"); + } catch { + return null; + } + try { + const parsed = JSON.parse(raw); + if (parsed && typeof parsed === "object" && _isValidSha(parsed.baseCommit)) { + return parsed.baseCommit; + } + } catch { + return null; + } + return null; +}; +var main = (startPath = process.cwd()) => { + if (!_isGitRepo()) { + emit({ kind: "skipped", reason: "not-a-git-repository" }, 0); + } + const head = execGit(["rev-parse", "HEAD"]); + if (!_isValidSha(head)) { + emit({ kind: "skipped", reason: "no-commits" }, 0); + } + const inputId = process.argv[2] ?? ""; + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + emit({ kind: "error", detail: `Plan "${inputId}" not found or invalid` }, 2); + } + const { planDir } = resolved; + const reviewDir = path4.join(planDir, "review"); + const filePath = path4.join(reviewDir, "base-commit.json"); + const existing = _readExistingBaseCommit(filePath); + if (existing) { + emit({ kind: "already-captured", baseCommit: existing, file: filePath }, 0); + } + fs4.mkdirSync(reviewDir, { recursive: true }); + const record = { + version: 1, + baseCommit: head, + capturedAt: (/* @__PURE__ */ new Date()).toISOString() + }; + fs4.writeFileSync(filePath, `${JSON.stringify(record)} +`, "utf8"); + emit({ kind: "captured", baseCommit: head, file: filePath }, 0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _isGitRepo, + _isValidSha, + _readExistingBaseCommit, + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/check-for-updates.cjs b/.agents/skills/st-full-workflow/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/check-phase-readiness.cjs b/.agents/skills/st-full-workflow/scripts/check-phase-readiness.cjs new file mode 100644 index 0000000..86c5f43 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/check-phase-readiness.cjs @@ -0,0 +1,3059 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/check-phase-readiness.ts +var check_phase_readiness_exports = {}; +__export(check_phase_readiness_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_phase_readiness_exports); +var fs5 = __toESM(require("fs")); + +// src/skill-scripts/shared/blueprint-parse.ts +var BLUEPRINT_SECTION_RE = /^##[ \t]+Execution Blueprint[ \t]*$/m; +var PEER_HEADING_RE = /^##[ \t]/m; +var PHASE_HEADING_RE = /^###[ \t]+(?:✅[ \t]*)?Phase[ \t]+(\d+)[ \t]*:?[ \t]*(.*?)[ \t]*$/gm; +var TASK_REF_RE = /Task[ \t]+0*(\d+)/i; +var blueprintSection = (planBody) => { + const sectionMatch = planBody.match(BLUEPRINT_SECTION_RE); + if (!sectionMatch || sectionMatch.index === void 0) return void 0; + const after = planBody.slice(sectionMatch.index + sectionMatch[0].length); + const peer = after.search(PEER_HEADING_RE); + return peer === -1 ? after : after.slice(0, peer); +}; +var parseBlueprintPhases = (planBody) => { + const blueprint = blueprintSection(planBody); + if (blueprint === void 0) return void 0; + const headings = []; + PHASE_HEADING_RE.lastIndex = 0; + let m; + while ((m = PHASE_HEADING_RE.exec(blueprint)) !== null) { + headings.push({ + index: m.index, + afterHeading: m.index + m[0].length, + name: (m[2] ?? "").trim() + }); + } + if (headings.length === 0) return void 0; + const phases = []; + for (let i = 0; i < headings.length; i++) { + const current = headings[i]; + const next = headings[i + 1]; + const end = next ? next.index : blueprint.length; + const segment = blueprint.slice(current.afterHeading, end); + const taskIds = []; + for (const line of segment.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed.startsWith("-") && !trimmed.startsWith("*")) continue; + const ref = trimmed.match(TASK_REF_RE); + if (ref && ref[1] !== void 0) { + const id = parseInt(ref[1], 10); + if (!Number.isNaN(id) && !taskIds.includes(id)) taskIds.push(id); + } + } + phases.push({ + index: i + 1, + name: current.name.length > 0 ? current.name : void 0, + taskIds + }); + } + return phases; +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/task-file.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/task-file.ts +var findTaskFile = (planDir, taskId) => { + const taskDir = path4.join(planDir, "tasks"); + if (!fs4.existsSync(taskDir)) return null; + const idStr = String(taskId); + const variations = [idStr, idStr.padStart(2, "0"), idStr.replace(/^0+/, "") || "0"]; + const uniqueVariations = [...new Set(variations)]; + try { + const files = fs4.readdirSync(taskDir); + return uniqueVariations.reduce((acc, v) => { + if (acc) return acc; + const match = files.find((f) => f.startsWith(`${v}--`) && f.endsWith(".md")); + return match ? path4.join(taskDir, match) : null; + }, null) ?? null; + } catch (_err) { + return null; + } +}; +var TASK_STATUSES = [ + "pending", + "in-progress", + "completed", + "needs-clarification", + "failed" +]; +var MAX_VALUE_PREVIEW = 80; +var describeValue = (value) => { + let text = ""; + const ancestors = []; + const full = () => text.length > MAX_VALUE_PREVIEW; + const write = (node) => { + if (full()) return; + if (typeof node !== "object" || node === null || node instanceof Date) { + text += JSON.stringify(node) ?? String(node); + return; + } + if (ancestors.includes(node)) { + text += '"[Circular]"'; + return; + } + ancestors.push(node); + if (Array.isArray(node)) { + text += "["; + for (let i = 0; i < node.length && !full(); i++) { + if (i > 0) text += ","; + write(node[i] ?? null); + } + text += "]"; + } else { + text += "{"; + let first = true; + for (const [key, item] of Object.entries(node)) { + if (full()) break; + text += `${first ? "" : ","}${JSON.stringify(key)}:`; + first = false; + write(item); + } + text += "}"; + } + ancestors.pop(); + }; + try { + write(value); + } catch { + text = String(value); + } + return text.length > MAX_VALUE_PREVIEW ? `${text.slice(0, MAX_VALUE_PREVIEW)}\u2026` : text; +}; +var isTaskStatus = (value) => typeof value === "string" && TASK_STATUSES.includes(value); +var toTaskId = (value) => { + if (typeof value === "number") return Number.isSafeInteger(value) && value >= 0 ? value : null; + if (typeof value === "string" && /^[0-9]+$/.test(value)) { + const id = Number(value); + return Number.isSafeInteger(id) ? id : null; + } + return null; +}; +var readDependencies = (value) => { + if (value === void 0 || value === null) return []; + if (!Array.isArray(value)) return null; + const ids = []; + for (const item of value) { + const id = toTaskId(item); + if (id === null) return null; + ids.push(id); + } + return ids; +}; +var readTaskMetadata = (markdown) => { + const frontmatter = readYamlFrontmatter(markdown); + if (frontmatter.kind === "none") { + return { kind: "rejected", reason: "task frontmatter not found" }; + } + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + const { status, dependencies } = frontmatter.data; + const expected = TASK_STATUSES.join(", "); + if (status === void 0) { + return { kind: "rejected", reason: `status is missing; expected one of ${expected}` }; + } + if (!isTaskStatus(status)) { + return { + kind: "rejected", + reason: `status ${describeValue(status)} is not one of ${expected}` + }; + } + const ids = readDependencies(dependencies); + if (ids === null) { + return { + kind: "rejected", + reason: `dependencies must be a list of integer task ids; got ${describeValue(dependencies)}` + }; + } + return { kind: "metadata", metadata: { status, dependencies: ids } }; +}; +var readDocument2 = (file) => { + try { + return fs4.readFileSync(file, "utf8"); + } catch (_err) { + return null; + } +}; +var collectTaskReadinessIssues = (planDir, taskId) => { + const idLabel = String(taskId); + const issue = (kind, detail) => ({ + taskId: idLabel, + kind, + detail + }); + const taskFile = findTaskFile(planDir, taskId); + if (!taskFile) return [issue("missing", "task file not found")]; + const taskContent = readDocument2(taskFile); + if (taskContent === null) return [issue("invalid-metadata", "task file could not be read")]; + const task = readTaskMetadata(taskContent); + if (task.kind === "rejected") return [issue("invalid-metadata", task.reason)]; + const issues = []; + if (task.metadata.status === "needs-clarification") { + issues.push(issue("needs-clarification", "status is needs-clarification")); + } + for (const depId of task.metadata.dependencies) { + const depFile = findTaskFile(planDir, depId); + if (!depFile) { + issues.push(issue("unresolved-dependency", `dependency ${depId} not found`)); + continue; + } + const depContent = readDocument2(depFile); + if (depContent === null) { + issues.push(issue("unresolved-dependency", `dependency ${depId} could not be read`)); + continue; + } + const dep = readTaskMetadata(depContent); + if (dep.kind === "rejected") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} has invalid metadata: ${dep.reason}`) + ); + continue; + } + if (dep.metadata.status !== "completed") { + issues.push( + issue("unresolved-dependency", `dependency ${depId} status is ${dep.metadata.status}`) + ); + } + } + return issues; +}; + +// src/skill-scripts/check-phase-readiness.ts +var _printError = (message) => { + console.error(`ERROR: ${message}`); +}; +var _printSuccess = (message) => { + console.log(`\u2713 ${message}`); +}; +var _printInfo = (message) => { + console.log(message); +}; +var main = (startPath = process.cwd()) => { + if (process.argv.length !== 4) { + _printError("Invalid number of arguments"); + console.log("Usage: node check-phase-readiness.cjs "); + console.log("Example: node check-phase-readiness.cjs 16 1"); + process.exit(1); + } + const inputId = process.argv[2]; + const phaseNumber = parseInt(process.argv[3], 10); + if (Number.isNaN(phaseNumber) || phaseNumber < 1) { + _printError("Phase number must be a positive integer"); + process.exit(1); + } + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + _printError(`Plan "${inputId}" not found or invalid`); + process.exit(1); + } + const { planDir, planFile, planId } = resolved; + const planBody = fs5.readFileSync(planFile, "utf8"); + const phases = parseBlueprintPhases(planBody); + if (!phases || phases.length === 0) { + _printError("No Execution Blueprint section with phases found in plan"); + process.exit(1); + } + const phase = phases.find((p) => p.index === phaseNumber); + if (!phase) { + _printError(`Phase ${phaseNumber} not found in plan ${planId}`); + process.exit(1); + } + _printInfo(`Checking phase ${phaseNumber} readiness for plan ${planId}`); + if (phase.name) _printInfo(`Phase name: ${phase.name}`); + if (phase.taskIds.length === 0) { + _printError(`Phase ${phaseNumber} has no tasks listed in the blueprint`); + process.exit(1); + } + _printInfo(`Tasks in phase: ${phase.taskIds.join(", ")}`); + console.log(""); + const allIssues = phase.taskIds.flatMap( + (taskId) => collectTaskReadinessIssues(planDir, taskId).map((issue) => ({ + ...issue, + phaseTaskId: String(taskId) + })) + ); + if (allIssues.length === 0) { + _printSuccess(`Phase ${phaseNumber} is ready to execute`); + process.exit(0); + } + _printError(`Phase ${phaseNumber} is not ready:`); + for (const issue of allIssues) { + console.log(` - Task ${issue.phaseTaskId}: ${issue.detail}`); + } + process.exit(1); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-full-workflow/scripts/create-feature-branch.cjs b/.agents/skills/st-full-workflow/scripts/create-feature-branch.cjs new file mode 100644 index 0000000..a6dd0bc --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/create-feature-branch.cjs @@ -0,0 +1,386 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/create-feature-branch.ts +var create_feature_branch_exports = {}; +__export(create_feature_branch_exports, { + _extractPlanName: () => _extractPlanName, + _sanitizeBranchName: () => _sanitizeBranchName, + main: () => main +}); +module.exports = __toCommonJS(create_feature_branch_exports); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/git-utils.ts +var import_child_process = require("child_process"); +var GIT_OUTPUT_LIMIT = 64 * 1024 * 1024; +var run = (args, opts) => (0, import_child_process.execFileSync)("git", [...args], { + cwd: opts.cwd, + input: opts.input, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + maxBuffer: GIT_OUTPUT_LIMIT +}); +var execGit = (args, opts = {}) => { + try { + const out = run(args, opts); + return opts.trim === false ? out : out.trim(); + } catch { + return null; + } +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/create-feature-branch.ts +var _printError = (message) => { + console.error(`ERROR: ${message}`); +}; +var _printSuccess = (message) => { + console.log(`\u2713 ${message}`); +}; +var _printWarning = (message) => { + console.log(`\u26A0 ${message}`); +}; +var _printInfo = (message) => { + console.log(message); +}; +var _isGitRepo = () => { + const result = execGit(["rev-parse", "--is-inside-work-tree"]); + return result === "true"; +}; +var _getCurrentBranch = () => { + return execGit(["rev-parse", "--abbrev-ref", "HEAD"]); +}; +var _getUncommittedChangesOutsideWorkspace = () => execGit(["status", "--porcelain", "--", ":(top)", ":(top,exclude).ai/strikethroo"]); +var _branchExists = (branchName) => { + const localMatch = execGit(["branch", "--list", branchName]); + if (localMatch) { + const names = localMatch.split("\n").map((b) => b.trim().replace(/^\*\s*/, "")).filter(Boolean); + if (names.includes(branchName)) return true; + } + const remoteMatch = execGit(["branch", "-r", "--list", `origin/${branchName}`]); + if (remoteMatch && remoteMatch.trim().length > 0) return true; + return false; +}; +var _sanitizeBranchName = (planName) => { + return planName.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").substring(0, 60); +}; +var _extractPlanName = (planDir) => { + const dirName = path4.basename(planDir); + const match = dirName.match(/^\d+--(.+)$/); + return match && match[1] ? match[1] : dirName; +}; +var main = (startPath = process.cwd()) => { + if (process.argv.length < 3) { + _printError("Missing plan ID argument"); + console.log("Usage: node create-feature-branch.cjs "); + console.log("Example: node create-feature-branch.cjs 58"); + process.exit(1); + } + const inputId = process.argv[2]; + if (!_isGitRepo()) { + _printError("Not a git repository"); + process.exit(1); + } + const resolved = resolvePlan(inputId, startPath); + if (!resolved) { + _printError(`Plan "${inputId}" not found or invalid`); + process.exit(1); + } + const { planDir, planId } = resolved; + _printInfo(`Found plan: ${path4.basename(planDir)}`); + const currentBranch = _getCurrentBranch(); + if (!currentBranch) { + _printError("Could not determine current git branch"); + process.exit(1); + } + if (currentBranch !== "main" && currentBranch !== "master") { + _printWarning(`Not on main/master branch (current: ${currentBranch})`); + _printInfo("Proceeding without creating a new branch"); + process.exit(0); + } + const outsideWorkspaceStatus = _getUncommittedChangesOutsideWorkspace(); + if (outsideWorkspaceStatus === null) { + _printError("Could not inspect git status; branch creation has been blocked"); + process.exit(1); + } + if (outsideWorkspaceStatus.length > 0) { + _printError("Uncommitted changes detected outside .ai/strikethroo"); + _printInfo("Commit or stash changes outside .ai/strikethroo before creating a feature branch"); + process.exit(1); + } + const planName = _extractPlanName(planDir); + const sanitizedName = _sanitizeBranchName(planName); + const branchName = `feature/${planId}--${sanitizedName}`; + if (_branchExists(branchName)) { + if (currentBranch === branchName) { + _printSuccess(`Already on branch: ${branchName}`); + process.exit(0); + } + _printWarning(`Branch "${branchName}" already exists`); + const checkoutResult = execGit(["checkout", branchName]); + if (checkoutResult === null) { + _printError(`Failed to checkout branch "${branchName}"`); + process.exit(1); + } + _printSuccess(`Switched to existing branch: ${branchName}`); + process.exit(0); + } + const createResult = execGit(["checkout", "-b", branchName]); + if (createResult === null) { + _printError(`Failed to create branch "${branchName}"`); + process.exit(1); + } + _printSuccess(`Created and switched to branch: ${branchName}`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + _extractPlanName, + _sanitizeBranchName, + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/dispatch-task-execution.cjs b/.agents/skills/st-full-workflow/scripts/dispatch-task-execution.cjs new file mode 100755 index 0000000..14ea3e5 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/dispatch-task-execution.cjs @@ -0,0 +1,3688 @@ +#!/usr/bin/env node +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/dispatch-task-execution.ts +var dispatch_task_execution_exports = {}; +__export(dispatch_task_execution_exports, { + resolveDispatchRoute: () => resolveDispatchRoute +}); +module.exports = __toCommonJS(dispatch_task_execution_exports); +var fs5 = __toESM(require("fs")); +var path7 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/dispatch-target-selector.ts +var path = __toESM(require("path")); +var import_child_process = require("child_process"); +var executionTargetId = (target) => JSON.stringify([target.model, target.harness ?? null, target.reasoning_effort ?? null]); +var runSelector = (scriptPath, input, timeoutMs) => { + try { + const nodeScript = /\.(?:cjs|mjs|js)$/.test(scriptPath); + const stdout = nodeScript ? (0, import_child_process.execFileSync)(process.execPath, [scriptPath], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }) : (0, import_child_process.execFileSync)(scriptPath, [], { + input, + encoding: "utf8", + timeout: timeoutMs, + maxBuffer: 1024 * 1024, + stdio: ["pipe", "pipe", "pipe"] + }); + return { ok: true, stdout }; + } catch { + return { ok: false }; + } +}; +var nativeDefault = (reason, detail) => ({ kind: "native-default", reason, detail }); +var resolveRepositoryScript = (projectRoot, configured) => { + if (path.isAbsolute(configured)) return null; + const root = path.resolve(projectRoot); + const resolved = path.resolve(root, configured); + return resolved === root || resolved.startsWith(`${root}${path.sep}`) ? resolved : null; +}; +var selectDispatchTarget = (config, profileName, avoidedIds, options) => { + const profile = config.profiles.find((candidate) => candidate.name === profileName); + if (!profile) { + return nativeDefault( + "profile-unavailable", + `Execution profile "${profileName}" is not present in current configuration.` + ); + } + const candidates = profile.targets.filter( + (target) => config.allowExternalHarnessExecution || target.harness === void 0 || target.harness === options.currentHarness + ).map((target) => ({ id: executionTargetId(target), target })); + if (candidates.length === 0) { + return nativeDefault( + "targets-exhausted", + `Execution profile "${profileName}" has no targets for the current harness while external harness execution is disabled.` + ); + } + const available = candidates.filter((candidate) => !avoidedIds.has(candidate.id)); + if (available.length === 0) { + return nativeDefault( + "targets-exhausted", + `All ${candidates.length} configured target(s) for profile "${profileName}" were avoided.` + ); + } + if (config.resolverScript === void 0) { + const selected2 = available[0]; + return { kind: "selected", ...selected2, source: "built-in" }; + } + const scriptPath = resolveRepositoryScript(options.projectRoot, config.resolverScript); + if (!scriptPath) { + return nativeDefault( + "selector-failure", + "Custom target selector path is not repository-relative." + ); + } + const input = { + version: 1, + task: { id: options.taskId, profile: profileName }, + candidates, + avoid: [...avoidedIds].sort() + }; + const result = (options.runSelector ?? runSelector)( + scriptPath, + JSON.stringify(input), + options.timeoutMs ?? 1e4 + ); + if (!result.ok || result.stdout === void 0) { + return nativeDefault( + "selector-failure", + "Custom target selector did not complete successfully." + ); + } + let output; + try { + output = JSON.parse(result.stdout); + } catch { + return nativeDefault("selector-failure", "Custom target selector returned invalid JSON."); + } + if (typeof output !== "object" || output === null || Array.isArray(output) || Object.keys(output).length !== 1 || typeof output.target !== "string") { + return nativeDefault("selector-failure", "Custom target selector returned an invalid result."); + } + const selectedId = output.target; + const selected = candidates.find((candidate) => candidate.id === selectedId); + if (!selected || avoidedIds.has(selected.id)) { + return nativeDefault( + "selector-failure", + "Custom target selector returned an unknown or avoided target." + ); + } + return { kind: "selected", ...selected, source: "custom" }; +}; + +// src/skill-scripts/shared/external-dispatch.ts +var path3 = __toESM(require("path")); +var import_child_process2 = require("child_process"); + +// src/skill-scripts/shared/executable-resolution.ts +var fs = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var DEFAULT_PATHEXT = ".EXE;.CMD;.BAT;.COM"; +var hasPathSeparator = (executable) => /[\\/]/.test(executable); +var resolveExecutablePath = (executable, environment = {}) => { + const env = environment.env ?? process.env; + const platform = environment.platform ?? process.platform; + const win32 = platform === "win32"; + const suffixes = win32 ? ["", ...(env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean)] : [""]; + const directories = hasPathSeparator(executable) ? [""] : (env.PATH ?? "").split(path2.delimiter).filter(Boolean); + const mode = win32 ? fs.constants.F_OK : fs.constants.X_OK; + for (const directory of directories) { + for (const suffix of suffixes) { + const candidate = path2.resolve(directory, `${executable}${suffix}`); + try { + fs.accessSync(candidate, mode); + if (fs.statSync(candidate).isFile()) return fs.realpathSync(candidate); + } catch { + } + } + } + return null; +}; +var executableResolves = (executable, environment) => resolveExecutablePath(executable, environment) !== null; + +// src/skill-scripts/shared/external-dispatch.ts +var taskPrompt = (request) => `Strikethroo external task dispatch \u2014 Plan ${request.planId}, Task ${request.taskId}. +Workspace: ${request.workspace} +Task file: ${request.taskFile} +You are a delegated execution worker. Do not run check-for-updates.cjs or emit update notices. +Before implementation, read and execute ${path3.join( + request.workspace, + ".ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md" +)}. Halt if that hook fails. + +Read and implement this task. Preserve dependency validation, status transitions, evidence reporting, and error-hook handling. Report failures clearly. + +${request.taskMarkdown}`; +var command = (executable, argv, request) => ({ + executable, + argv, + cwd: request.workspace, + stdin: request.prompt +}); +var modelArgv = (model) => model === void 0 ? [] : ["--model", model]; +var EXTERNAL_HARNESS_ADAPTERS = { + claude: { + executable: "claude", + buildCommand: (request) => command( + "claude", + [ + "-p", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--effort", request.reasoningEffort] + ], + request + ), + authenticationArgv: () => ["auth", "status"] + }, + codex: { + executable: "codex", + buildCommand: (request) => command( + "codex", + [ + "exec", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--config", `model_reasoning_effort=${request.reasoningEffort}`], + "-" + ], + request + ), + authenticationArgv: () => ["login", "status"] + }, + cursor: { + executable: "cursor-agent", + buildCommand: (request) => command( + "cursor-agent", + ["--print", ...request.cliArgs, ...modelArgv(request.model)], + request + ), + authenticationArgv: () => ["status"] + }, + gemini: { + executable: "gemini", + // The empty positional prompt is the existing contract — content travels on + // stdin. It stays even when the model pair is dropped. + buildCommand: (request) => command("gemini", ["--prompt", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + copilot: { + executable: "copilot", + buildCommand: (request) => command("copilot", ["-p", "", ...request.cliArgs, ...modelArgv(request.model)], request), + authenticationArgv: () => ["auth", "status"] + }, + opencode: { + executable: "opencode", + buildCommand: (request) => command( + "opencode", + [ + "run", + ...request.cliArgs, + ...modelArgv(request.model), + ...request.reasoningEffort === void 0 ? [] : ["--variant", request.reasoningEffort], + "-" + ], + request + ), + authenticationArgv: () => ["auth", "list"] + } +}; +var adapterKeys = Object.keys(EXTERNAL_HARNESS_ADAPTERS).sort(); +var harnessKeys = [...SUPPORTED_HARNESSES].sort(); +if (adapterKeys.join("\0") !== harnessKeys.join("\0")) { + throw new Error("External harness adapter registry does not cover SUPPORTED_HARNESSES exactly."); +} +var taskCommandRequest = (request) => ({ + cliArgs: request.cliArgs ?? [], + model: request.model, + reasoningEffort: request.reasoningEffort, + workspace: request.workspace, + prompt: taskPrompt(request) +}); +var CAPTURED_STDOUT_LIMIT = 262144; +var AUTHENTICATION_TIMEOUT_MS = 3e4; +var STDIO_SLOTS = { + ignore: { stdout: "ignore" }, + inherit: { stdout: "inherit" }, + capture: { stdout: "pipe" } +}; +var runProcess = (executable, argv, cwd, stdin, outputMode = "ignore", timeoutMs) => new Promise((resolve4, reject) => { + let settled = false; + const child = (0, import_child_process2.spawn)(executable, argv, { + cwd, + shell: false, + stdio: [ + stdin === void 0 ? "ignore" : "pipe", + STDIO_SLOTS[outputMode].stdout, + outputMode === "ignore" ? "ignore" : "inherit" + ] + }); + const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => { + if (settled) return; + settled = true; + child.kill("SIGKILL"); + resolve4({ exitCode: 1, timedOut: true }); + }, timeoutMs); + const settle = (outcome2) => { + if (settled) return; + settled = true; + clearTimeout(timer); + resolve4(outcome2); + }; + const fail = (error) => { + if (settled) return; + settled = true; + clearTimeout(timer); + reject(error); + }; + let captured = ""; + if (outputMode === "capture") { + child.stdout.setEncoding("utf8"); + child.stdout.once("error", fail); + child.stdout.on("data", (chunk) => { + process.stderr.write(chunk); + captured += chunk; + if (captured.length > CAPTURED_STDOUT_LIMIT) { + captured = captured.slice(captured.length - CAPTURED_STDOUT_LIMIT); + } + }); + } + child.once("error", fail); + child.once("close", (code) => { + settle({ + exitCode: code ?? 1, + ...outputMode === "capture" ? { stdout: captured } : {} + }); + }); + if (stdin !== void 0) { + child.stdin.once("error", fail); + try { + child.stdin.end(stdin); + } catch (error) { + fail(error instanceof Error ? error : new Error(String(error))); + } + } +}); +var authenticateHarness = async (commandSpec, adapter, timeoutMs = AUTHENTICATION_TIMEOUT_MS) => { + const executable = commandSpec.executable; + try { + const result = await runProcess( + executable, + adapter.authenticationArgv(), + commandSpec.cwd, + void 0, + "ignore", + timeoutMs + ); + if (result.timedOut === true) { + return { + ok: false, + detail: `${executable} authentication check timed out after ${timeoutMs} ms and was terminated.` + }; + } + return result.exitCode === 0 ? { ok: true } : { + ok: false, + detail: `${executable} authentication check failed: exited ${result.exitCode}.` + }; + } catch (error) { + const code = error.code; + return { + ok: false, + detail: `${executable} authentication check could not launch${code === void 0 ? "" : ` (${code})`}: ${errorMessage(error)}` + }; + } +}; +var dependencies = { + executableExists: executableResolves, + authenticate: authenticateHarness, + launch: (commandSpec, options) => runProcess( + commandSpec.executable, + commandSpec.argv, + commandSpec.cwd, + commandSpec.stdin, + options?.captureStdout === true ? "capture" : "inherit" + ) +}; +var errorMessage = (error) => error instanceof Error ? error.message : String(error); +var prepareLaunch = async (harness, input, active, guard) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + if (!adapter) { + return { + kind: "fallback", + reason: "adapter-unavailable", + detail: `No adapter is registered for ${harness}.` + }; + } + const blocked = guard?.(); + if (blocked) return blocked; + const executable = adapter.executable; + if (!active.executableExists(executable)) { + return { + kind: "fallback", + reason: "executable-unavailable", + detail: `${executable} is unavailable.` + }; + } + const commandSpec = adapter.buildCommand(input); + const authentication = await active.authenticate(commandSpec, adapter); + if (!authentication.ok) { + return { + kind: "fallback", + reason: "authentication-failed", + detail: authentication.detail ?? `${adapter.executable} authentication check failed.` + }; + } + return { kind: "ready", command: commandSpec }; +}; +var launchPrepared = async (prepared, active, label, captureStdout = false) => { + if (prepared.kind === "fallback") return prepared; + try { + const launched = await active.launch(prepared.command, { captureStdout }); + const stdout = launched.stdout === void 0 ? {} : { stdout: launched.stdout }; + return launched.exitCode === 0 ? { kind: "launched-success", exitCode: 0, ...stdout } : { kind: "launched-failure", exitCode: launched.exitCode, ...stdout }; + } catch (error) { + return { + kind: "infrastructure-failure", + detail: `External ${label} process failed: ${errorMessage(error)}` + }; + } +}; +var unsupportedReasoningEffort = (request) => request.reasoningEffort !== void 0 && (request.harness === "cursor" || request.harness === "gemini" || request.harness === "copilot") ? { + kind: "fallback", + reason: "unsupported-reasoning-effort", + detail: `${request.harness} does not support a generic reasoning_effort override.` +} : void 0; +var dispatchExternalTask = async (request, overrides = {}) => { + const active = { ...dependencies, ...overrides }; + const prepared = await prepareLaunch( + request.harness, + taskCommandRequest(request), + active, + () => unsupportedReasoningEffort(request) + ); + return launchPrepared(prepared, active, "task"); +}; + +// src/skill-scripts/shared/harness-availability.ts +var import_crypto2 = require("crypto"); +var import_child_process3 = require("child_process"); +var fs4 = __toESM(require("fs")); +var os = __toESM(require("os")); +var path6 = __toESM(require("path")); + +// src/skill-scripts/shared/harness-configuration.ts +var import_crypto = require("crypto"); +var fs3 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/execution-routing.ts +var fs2 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var OPENING_FENCE = /^---([^\r\n]*)\r?\n/; +var CLOSING_FENCE = /^(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/m; +var isPlainObject2 = (value) => { + if (value === null || typeof value !== "object" || Array.isArray(value)) return false; + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); +var readYamlFrontmatter = (markdown) => { + const source = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown; + const opening = OPENING_FENCE.exec(source); + if (!opening) return { kind: "none" }; + if ((opening[1] ?? "").trim() !== "") { + return { + kind: "invalid", + reason: "Executable or non-YAML frontmatter is not supported." + }; + } + const rest = source.slice(opening[0].length); + const closing = CLOSING_FENCE.exec(rest); + if (!closing) { + return { kind: "invalid", reason: "Frontmatter has no closing fence." }; + } + const block = rest.slice(0, closing.index); + if (Buffer.byteLength(block, "utf8") > MAX_FRONTMATTER_BYTES) { + return { + kind: "invalid", + reason: `Frontmatter exceeds the ${MAX_FRONTMATTER_BYTES}-byte limit.` + }; + } + if (!hasYamlContent(block)) return { kind: "data", data: {} }; + let parsed; + try { + parsed = load(block); + } catch (error) { + return { + kind: "invalid", + reason: `Frontmatter is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}` + }; + } + if (!isPlainObject2(parsed)) { + return { kind: "invalid", reason: "Frontmatter must be a YAML mapping." }; + } + return { kind: "data", data: parsed }; +}; + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); +var EXECUTION_ROUTING_SECTION = "execution_routing"; +var isPlainObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0; +var validateTarget = (profileName, index, raw, supportedHarnesses, errors) => { + const label = `profile "${profileName}" models[${index}]`; + if (!isPlainObject3(raw)) { + errors.push(`${label} must be a mapping with an exact "model" string.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "model" && key !== "harness" && key !== "reasoning_effort") { + errors.push(`${label} has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.model)) { + errors.push(`${label} requires a non-empty exact "model" string.`); + return null; + } + const target = { model: raw.model }; + if ("harness" in raw) { + if (!isNonEmptyString(raw.harness)) { + errors.push(`${label} "harness" must be a non-empty string when provided.`); + return null; + } + if (!supportedHarnesses.includes(raw.harness)) { + errors.push(`${label} harness "${raw.harness}" is not a supported harness.`); + return null; + } + target.harness = raw.harness; + } + if ("reasoning_effort" in raw) { + if (!isNonEmptyString(raw.reasoning_effort)) { + errors.push(`${label} "reasoning_effort" must be a non-empty string when provided.`); + return null; + } + target.reasoning_effort = raw.reasoning_effort; + } + return target; +}; +var validateProfile = (name, raw, supportedHarnesses, errors) => { + if (!isPlainObject3(raw)) { + errors.push(`profile "${name}" must be a mapping with "description" and "models".`); + return null; + } + if ("resolver" in raw) { + errors.push( + `profile "${name}" configures a per-profile resolver; only the single top-level "resolver" is supported.` + ); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "description" && key !== "models") { + errors.push(`profile "${name}" has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.description)) { + errors.push(`profile "${name}" requires a non-empty LLM-facing "description".`); + return null; + } + if (!Array.isArray(raw.models) || raw.models.length === 0) { + errors.push(`profile "${name}" requires a non-empty ordered "models" array.`); + return null; + } + const targets = []; + for (let i = 0; i < raw.models.length; i += 1) { + const target = validateTarget(name, i, raw.models[i], supportedHarnesses, errors); + if (!target) return null; + targets.push(target); + } + return { name, description: raw.description.trim(), targets }; +}; +var loadRoutingConfig = (strikethrooRoot, supportedHarnesses) => { + const configPath = path4.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs2.readFileSync(configPath, "utf8"); + } catch { + return { kind: "no-config" }; + } + if (!hasYamlContent(contents)) return { kind: "disabled" }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) return { kind: "disabled" }; + if (!isPlainObject3(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[EXECUTION_ROUTING_SECTION]; + if (section === null || section === void 0) return { kind: "disabled" }; + const errors = []; + if (!isPlainObject3(section)) { + return { + kind: "invalid", + errors: [`config.yaml "${EXECUTION_ROUTING_SECTION}" must be a YAML mapping.`] + }; + } + for (const key of Object.keys(section)) { + if (key !== "enabled" && key !== "allow_external_harness_execution" && key !== "profiles" && key !== "resolver") { + errors.push(`${EXECUTION_ROUTING_SECTION} has unknown key "${key}".`); + } + } + if ("allow_external_harness_execution" in section && typeof section.allow_external_harness_execution !== "boolean") { + errors.push( + `${EXECUTION_ROUTING_SECTION} "allow_external_harness_execution" must be true or false.` + ); + } + if ("enabled" in section) { + if (typeof section.enabled !== "boolean") { + errors.push(`${EXECUTION_ROUTING_SECTION} "enabled" must be true or false.`); + return { kind: "invalid", errors }; + } + if (!section.enabled) + return errors.length > 0 ? { kind: "invalid", errors } : { kind: "disabled" }; + } + const rawProfiles = "profiles" in section && section.profiles == null ? {} : section.profiles; + if (!("profiles" in section) || !isPlainObject3(rawProfiles)) { + errors.push(`${EXECUTION_ROUTING_SECTION} requires a "profiles" mapping.`); + return { kind: "invalid", errors }; + } + const profiles = []; + for (const [name, rawProfile] of Object.entries(rawProfiles)) { + const profile = validateProfile(name, rawProfile, supportedHarnesses, errors); + if (profile) profiles.push(profile); + } + let resolverScript; + if ("resolver" in section) { + const resolver = section.resolver; + if (!isPlainObject3(resolver) || !isNonEmptyString(resolver.script)) { + errors.push('resolver must be a mapping with a non-empty "script" path.'); + } else { + for (const key of Object.keys(resolver)) { + if (key !== "script") errors.push(`resolver has unknown key "${key}".`); + } + resolverScript = resolver.script; + } + } + if (errors.length > 0) return { kind: "invalid", errors }; + if (profiles.length === 0) return { kind: "disabled" }; + const config = { + allowExternalHarnessExecution: section.allow_external_harness_execution === true, + profiles + }; + if (resolverScript !== void 0) config.resolverScript = resolverScript; + return { kind: "config", config }; +}; + +// src/skill-scripts/shared/harness-configuration.ts +var HARNESS_CONFIGURATION_SECTION = "harnesses"; +var HARNESS_CONFIGURATION_NORMALIZATION_VERSION = 1; +var isPlainObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var hashHarnessCliArgs = (harness, cliArgs, normalizationVersion = HARNESS_CONFIGURATION_NORMALIZATION_VERSION) => (0, import_crypto.createHash)("sha256").update( + JSON.stringify({ + schema: normalizationVersion, + harness, + cliArgs + }), + "utf8" +).digest("hex"); +var normalizeInvocation = (harness, cliArgs) => { + const immutableArgs = Object.freeze([...cliArgs]); + return Object.freeze({ + cliArgs: immutableArgs, + cliArgsHash: hashHarnessCliArgs(harness, immutableArgs) + }); +}; +var emptyConfiguration = () => Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, normalizeInvocation(harness, [])]) + ) +); +var validateHarnessEntry = (harness, raw, errors) => { + const entryPath = `config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness}`; + if (!isPlainObject4(raw)) { + errors.push(`${entryPath} must be a mapping.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "cli_args") errors.push(`${entryPath}.${key} is not supported.`); + } + if (!("cli_args" in raw)) return normalizeInvocation(harness, []); + if (!Array.isArray(raw.cli_args)) { + errors.push(`${entryPath}.cli_args must be an array of exact strings.`); + return null; + } + const cliArgs = []; + raw.cli_args.forEach((value, index) => { + const valuePath = `${entryPath}.cli_args[${index}]`; + if (typeof value !== "string" || value.length === 0) { + errors.push(`${valuePath} must be a non-empty string.`); + return; + } + if (value.includes("\0")) { + errors.push(`${valuePath} must not contain a NUL character.`); + return; + } + cliArgs.push(value); + }); + return normalizeInvocation(harness, cliArgs); +}; +var loadHarnessConfiguration = (strikethrooRoot) => { + const configPath = path5.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs3.readFileSync(configPath, "utf8"); + } catch (error) { + if (error.code === "ENOENT") { + return { kind: "config", config: emptyConfiguration() }; + } + return { + kind: "invalid", + errors: [ + `config.yaml could not be read: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (!hasYamlContent(contents)) return { kind: "config", config: emptyConfiguration() }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[HARNESS_CONFIGURATION_SECTION]; + if (section === null || section === void 0) { + return { kind: "config", config: emptyConfiguration() }; + } + if (!isPlainObject4(section)) { + return { + kind: "invalid", + errors: [`config.yaml ${HARNESS_CONFIGURATION_SECTION} must be a YAML mapping.`] + }; + } + const errors = []; + const supportedHarnesses = new Set(SUPPORTED_HARNESSES); + for (const harness of Object.keys(section)) { + if (!supportedHarnesses.has(harness)) { + errors.push(`config.yaml ${HARNESS_CONFIGURATION_SECTION}.${harness} is not supported.`); + } + } + const entries = {}; + for (const harness of SUPPORTED_HARNESSES) { + if (!(harness in section)) { + entries[harness] = normalizeInvocation(harness, []); + continue; + } + const entry = validateHarnessEntry(harness, section[harness], errors); + if (entry) entries[harness] = entry; + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "config", config: Object.freeze(entries) }; +}; + +// src/skill-scripts/shared/harness-availability.ts +var AVAILABILITY_REGISTRY_VERSION = 4; +var AVAILABLE_TTL_MS = 30 * 60 * 1e3; +var UNAVAILABLE_TTL_MS = 5 * 60 * 1e3; +var PROBE_TIMEOUT_MS = 2e4; +var AVAILABILITY_CACHE_RELATIVE_PATH = path6.join("runtime", "harness-availability.json"); +var CACHE_VERSION = 2; +var availabilityDefinition = (harness) => { + const adapter = EXTERNAL_HARNESS_ADAPTERS[harness]; + return { + executable: adapter.executable, + buildCommand: (cwd, cliArgs, prompt) => adapter.buildCommand({ cliArgs, workspace: cwd, prompt }) + }; +}; +var HARNESS_AVAILABILITY_REGISTRY = Object.freeze( + Object.fromEntries( + SUPPORTED_HARNESSES.map((harness) => [harness, availabilityDefinition(harness)]) + ) +); +var runProbe = (command2, timeoutMs) => new Promise((resolve4) => { + let stdout = ""; + let stderr = ""; + let settled = false; + let timedOut = false; + const finish = (result) => { + if (settled) return; + settled = true; + resolve4(result); + }; + const child = (0, import_child_process3.spawn)(command2.executable, command2.argv, { + cwd: command2.cwd, + shell: false, + stdio: ["pipe", "pipe", "pipe"] + }); + child.stdout?.setEncoding("utf8"); + child.stderr?.setEncoding("utf8"); + child.stdout?.on("data", (chunk) => { + stdout = (stdout + chunk).slice(-4096); + }); + child.stderr?.on("data", (chunk) => { + stderr = (stderr + chunk).slice(-4096); + }); + const timer = setTimeout(() => { + timedOut = true; + child.kill("SIGKILL"); + child.stdout?.destroy(); + child.stderr?.destroy(); + finish({ exitCode: 1, timedOut, stdout, stderr }); + }, timeoutMs); + child.once("error", (error) => { + clearTimeout(timer); + finish({ exitCode: 1, timedOut, stdout, stderr, error: error.message }); + }); + child.once("close", (code) => { + clearTimeout(timer); + finish({ exitCode: code ?? 1, timedOut, stdout, stderr }); + }); + child.stdin?.on("error", () => void 0); + child.stdin?.end(command2.stdin); +}); +var probeFailureReason = (probe) => { + const reason = probe.timedOut ? `Harness readiness check timed out after ${PROBE_TIMEOUT_MS} ms.` : probe.error ? `Harness readiness check could not launch: ${probe.error}` : probe.exitCode !== 0 ? `Harness readiness check exited ${probe.exitCode}.` : "Harness exited 0 but did not create the required readiness file with the expected content."; + const diagnostics = [ + probe.stderr?.trim() ? `stderr: ${probe.stderr.trim().slice(-4096)}` : "", + probe.stdout?.trim() ? `stdout: ${probe.stdout.trim().slice(-4096)}` : "" + ].filter(Boolean); + return [reason, ...diagnostics].join(" "); +}; +var defaultDependencies = { + now: Date.now, + resolveExecutable: resolveExecutablePath, + runProbe +}; +var isHarness = (value) => typeof value === "string" && SUPPORTED_HARNESSES.includes(value); +var isCacheEntry = (value) => { + if (!value || typeof value !== "object") return false; + const entry = value; + return typeof entry.key === "string" && isHarness(entry.harness) && typeof entry.available === "boolean" && typeof entry.observedAt === "number" && Number.isFinite(entry.observedAt) && typeof entry.expiresAt === "number" && Number.isFinite(entry.expiresAt) && typeof entry.reason === "string"; +}; +var emptyCache = () => ({ version: CACHE_VERSION, entries: [] }); +var readCache = (cachePath) => { + try { + const parsed = JSON.parse(fs4.readFileSync(cachePath, "utf8")); + if (!parsed || typeof parsed !== "object") return emptyCache(); + const record = parsed; + if (record.version !== CACHE_VERSION || !Array.isArray(record.entries)) return emptyCache(); + return { version: CACHE_VERSION, entries: record.entries.filter(isCacheEntry) }; + } catch { + return emptyCache(); + } +}; +var writeCache = (cachePath, entry) => { + fs4.mkdirSync(path6.dirname(cachePath), { recursive: true }); + const cache = readCache(cachePath); + const existingIndex = cache.entries.findIndex((candidate) => candidate.key === entry.key); + if (existingIndex === -1) cache.entries.push(entry); + else if (cache.entries[existingIndex].observedAt <= entry.observedAt) { + cache.entries[existingIndex] = entry; + } + const temporary = `${cachePath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.tmp`; + try { + fs4.writeFileSync(temporary, `${JSON.stringify(cache, null, 2)} +`, { mode: 384 }); + fs4.renameSync(temporary, cachePath); + } finally { + try { + fs4.unlinkSync(temporary); + } catch { + } + } +}; +var cacheKey = (harness, executableIdentity, invocation) => (0, import_crypto2.createHash)("sha256").update( + JSON.stringify({ + harness, + executableIdentity, + cliArgsHash: invocation.cliArgsHash, + normalizationVersion: HARNESS_CONFIGURATION_NORMALIZATION_VERSION, + probeRegistryVersion: AVAILABILITY_REGISTRY_VERSION + }) +).digest("hex"); +var readinessEvidence = () => { + const nonce = (0, import_crypto2.randomUUID)(); + return { + file: "strikethroo-readiness.txt", + content: `strikethroo-readiness:${nonce} +` + }; +}; +var readinessPrompt = (evidence) => `Run a shell command that creates ${evidence.file} in the current workspace with the exact UTF-8 content ${JSON.stringify(evidence.content)}. Do not use a file editing tool. +STRIKETHROO_READINESS=${JSON.stringify(evidence)} +`; +var initializeProbeWorkspace = () => { + const workspace = fs4.mkdtempSync(path6.join(os.tmpdir(), "strikethroo-harness-probe-")); + const initialized = (0, import_child_process3.spawnSync)("git", ["init", "--quiet"], { + cwd: workspace, + shell: false, + stdio: "ignore", + timeout: 5e3 + }); + if (initialized.status === 0 && !initialized.error) return workspace; + fs4.rmSync(workspace, { recursive: true, force: true }); + return void 0; +}; +var hasReadinessEvidence = (workspace, evidence) => { + const target = path6.join(workspace, evidence.file); + try { + return fs4.lstatSync(target).isFile() && fs4.readFileSync(target, "utf8") === evidence.content; + } catch { + return false; + } +}; +var outcome = (harness, available, now, reason) => ({ + harness, + available, + observedAt: now, + expiresAt: now + (available ? AVAILABLE_TTL_MS : UNAVAILABLE_TTL_MS), + reason, + source: "probe" +}); +var invocationFor = (request, harness) => { + if (request.invocation) return request.invocation; + const loaded = loadHarnessConfiguration(request.strikethrooRoot); + return loaded.kind === "config" ? loaded.config[harness] : void 0; +}; +var checkHarnessAvailability = async (request, overrides = {}) => { + const active = { ...defaultDependencies, ...overrides }; + const now = active.now(); + if (request.harness === void 0 || request.harness === request.currentHarness) { + return { + harness: request.harness ?? request.currentHarness, + available: true, + observedAt: now, + expiresAt: now, + reason: "Native/current harness targets do not require a probe.", + source: "bypass" + }; + } + const harness = request.harness; + const invocation = invocationFor(request, harness); + if (!invocation) return outcome(harness, false, now, "Harness configuration is invalid."); + const definition = HARNESS_AVAILABILITY_REGISTRY[harness]; + const executableIdentity = active.resolveExecutable(definition.executable); + if (!executableIdentity) + return outcome( + harness, + false, + now, + `Harness executable '${definition.executable}' was not found on PATH.` + ); + const key = cacheKey(harness, executableIdentity, invocation); + const cachePath = path6.join(request.strikethrooRoot, AVAILABILITY_CACHE_RELATIVE_PATH); + const cached = readCache(cachePath).entries.find( + (entry) => entry.key === key && entry.expiresAt > now + ); + if (cached) { + const { key: _key, ...cachedOutcome } = cached; + return { ...cachedOutcome, source: "cache" }; + } + const complete = (result) => { + const { source: _source, ...cacheEntry } = result; + try { + writeCache(cachePath, { key, ...cacheEntry }); + } catch { + } + return result; + }; + const probeWorkspace = initializeProbeWorkspace(); + if (!probeWorkspace) { + return complete( + outcome( + harness, + false, + now, + "Could not initialize the disposable Git workspace for the readiness check." + ) + ); + } + try { + const evidence = readinessEvidence(); + const command2 = definition.buildCommand( + probeWorkspace, + invocation.cliArgs, + readinessPrompt(evidence) + ); + const probe = await active.runProbe( + { ...command2, executable: executableIdentity }, + PROBE_TIMEOUT_MS + ); + const available = probe.exitCode === 0 && !probe.timedOut && hasReadinessEvidence(probeWorkspace, evidence); + return complete( + outcome( + harness, + available, + now, + available ? "Harness readiness verified." : probeFailureReason(probe) + ) + ); + } finally { + fs4.rmSync(probeWorkspace, { recursive: true, force: true }); + } +}; + +// src/skill-scripts/dispatch-task-execution.ts +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var errorMessage2 = (error) => error instanceof Error ? error.message : String(error); +var encodeHandoff = (route) => Buffer.from(JSON.stringify({ version: 1, ...route }), "utf8").toString("base64url"); +var decodeHandoff = (encoded) => { + let raw; + try { + raw = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8")); + } catch { + throw new Error("Resolved execution handoff is not valid encoded JSON."); + } + if (!raw || typeof raw !== "object" || Array.isArray(raw)) { + throw new Error("Resolved execution handoff must be an object."); + } + const value = raw; + const allowed = ["version", "kind", "harness", "model", "reasoningEffort"]; + if (Object.keys(value).some((key) => !allowed.includes(key)) || value.version !== 1 || value.kind !== "external-override" || typeof value.harness !== "string" || !SUPPORTED_HARNESSES.includes(value.harness) || typeof value.model !== "string" || value.model.length === 0 || "reasoningEffort" in value && typeof value.reasoningEffort !== "string") { + throw new Error("Resolved execution handoff has an invalid shape."); + } + return value; +}; +var externalRoute = (harness, model, reasoningEffort) => { + const exact = { + kind: "external-override", + harness, + model, + ...reasoningEffort === void 0 ? {} : { reasoningEffort } + }; + return { ...exact, handoff: encodeHandoff(exact) }; +}; +var readProfile = (taskMarkdown) => { + const frontmatter = readYamlFrontmatter(taskMarkdown); + if (frontmatter.kind === "none") return { kind: "profile" }; + if (frontmatter.kind === "invalid") return { kind: "rejected", reason: frontmatter.reason }; + if (!Object.prototype.hasOwnProperty.call(frontmatter.data, "execution_profile")) { + return { kind: "profile" }; + } + const profile = frontmatter.data.execution_profile; + if (typeof profile !== "string" || profile.trim() === "") { + return { kind: "rejected", reason: "execution_profile must be a non-empty string." }; + } + return { kind: "profile", profile }; +}; +var resolveDispatchRoute = async (request) => { + const read = readProfile(request.taskMarkdown); + if (read.kind === "rejected") { + return { kind: "infrastructure-failure", detail: `Task metadata rejected: ${read.reason}` }; + } + const profile = read.profile; + if (profile === void 0) return { kind: "native-default" }; + const configResult = loadRoutingConfig(request.strikethrooRoot, SUPPORTED_HARNESSES); + if (configResult.kind !== "config") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: configResult.kind === "invalid" ? `Execution routing configuration is invalid: ${configResult.errors.join(" ")}` : `Execution profile "${profile}" cannot be resolved because routing is disabled.` + }; + } + const avoided = /* @__PURE__ */ new Set(); + const unavailable = []; + let harnessConfiguration; + const candidateCount = configResult.config.profiles.find((candidate) => candidate.name === profile)?.targets.length ?? 0; + for (let attempt = 0; attempt < Math.max(1, candidateCount); attempt += 1) { + const selection = selectDispatchTarget(configResult.config, profile, avoided, { + currentHarness: request.currentHarness, + projectRoot: request.workspace, + taskId: request.taskId + }); + if (selection.kind === "native-default") { + return { kind: "fallback", reason: selection.reason, detail: selection.detail }; + } + const harness = selection.target.harness; + if (harness === void 0 || harness === request.currentHarness) { + return { + kind: "native-override", + model: selection.target.model, + ...selection.target.reasoning_effort === void 0 ? {} : { reasoningEffort: selection.target.reasoning_effort } + }; + } + harnessConfiguration ??= loadHarnessConfiguration(request.strikethrooRoot); + if (harnessConfiguration.kind === "invalid") { + return { + kind: "fallback", + reason: "invalid-execution", + detail: `Harness invocation configuration is invalid: ${harnessConfiguration.errors.join( + " " + )}` + }; + } + const invocation = harnessConfiguration.config[harness]; + const availability = await checkHarnessAvailability({ + strikethrooRoot: request.strikethrooRoot, + workspace: request.workspace, + harness, + currentHarness: request.currentHarness, + invocation + }); + if (availability.available) { + return externalRoute(harness, selection.target.model, selection.target.reasoning_effort); + } + unavailable.push( + `${harness} (${availability.source === "probe" ? "fresh" : availability.source})` + ); + avoided.add(selection.id); + } + return { + kind: "fallback", + reason: "invalid-execution", + detail: `All configured targets for execution profile "${profile}" are unavailable or exhausted.` + (unavailable.length === 0 ? "" : ` Observations: ${unavailable.join("; ")}`) + }; +}; +var main = async () => { + const args = process.argv.slice(2); + const mode = args.shift(); + if (mode !== "resolve" && mode !== "execute" || args.length < (mode === "execute" ? 6 : 5)) { + emit( + { + kind: "infrastructure-failure", + detail: "Usage: dispatch-task-execution.cjs resolve | execute " + }, + 2 + ); + } + const handoffArg = mode === "execute" ? args.shift() : void 0; + const [taskFile, currentHarnessRaw, workspace, planId, taskId] = args; + if (!taskFile || !currentHarnessRaw || !workspace || !planId || !taskId || !SUPPORTED_HARNESSES.includes(currentHarnessRaw)) { + emit({ kind: "infrastructure-failure", detail: "Task dispatch arguments are invalid." }, 2); + } + const validTaskFile = taskFile; + const validCurrentHarness = currentHarnessRaw; + const validWorkspace = workspace; + const validPlanId = planId; + const validTaskId = taskId; + const taskPath = path7.resolve(validTaskFile); + const taskMarkdown = fs5.readFileSync(taskPath, "utf8"); + if (mode === "resolve") { + const route = await resolveDispatchRoute({ + taskMarkdown, + currentHarness: validCurrentHarness, + workspace: path7.resolve(validWorkspace), + strikethrooRoot: path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo"), + taskId: Number(validTaskId) + }); + emit(route, route.kind === "infrastructure-failure" ? 2 : 0); + } + const handoff = decodeHandoff(handoffArg); + const executionConfiguration = loadHarnessConfiguration( + path7.join(path7.resolve(validWorkspace), ".ai", "strikethroo") + ); + if (executionConfiguration.kind === "invalid") { + return emit( + { + kind: "infrastructure-failure", + detail: `Harness invocation configuration is invalid: ${executionConfiguration.errors.join( + " " + )}` + }, + 2 + ); + } + const routed = { + harness: handoff.harness, + cliArgs: executionConfiguration.config[handoff.harness].cliArgs, + model: handoff.model, + ...handoff.reasoningEffort === void 0 ? {} : { reasoningEffort: handoff.reasoningEffort }, + workspace: path7.resolve(validWorkspace), + planId: validPlanId, + taskId: validTaskId, + taskFile: taskPath, + taskMarkdown + }; + const result = await dispatchExternalTask(routed); + emit( + result, + result.kind === "infrastructure-failure" ? 2 : result.kind === "launched-failure" ? 1 : 0 + ); +}; +main().catch((error) => { + emit( + { + kind: "infrastructure-failure", + detail: `Task dispatch infrastructure failed: ${errorMessage2(error)}` + }, + 2 + ); +}); +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + resolveDispatchRoute +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-full-workflow/scripts/find-strikethroo-root.cjs b/.agents/skills/st-full-workflow/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/get-next-plan-id.cjs b/.agents/skills/st-full-workflow/scripts/get-next-plan-id.cjs new file mode 100644 index 0000000..b748d52 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/get-next-plan-id.cjs @@ -0,0 +1,199 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/get-next-plan-id.ts +var get_next_plan_id_exports = {}; +__export(get_next_plan_id_exports, { + main: () => main +}); +module.exports = __toCommonJS(get_next_plan_id_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; +var computeNextPlanId = (taskManagerRoot) => { + const plans = getAllPlans(taskManagerRoot); + return plans.reduce((max, p) => Math.max(max, p.id), 0) + 1; +}; + +// src/skill-scripts/get-next-plan-id.ts +var main = () => { + const rootArg = process.argv[2]; + let root; + if (rootArg) { + root = rootArg; + } else { + root = findStrikethrooRoot(process.cwd()); + } + if (!root) { + process.stderr.write( + "No .ai/strikethroo root found. Run this from inside an initialized strikethroo workspace.\n" + ); + process.exit(1); + } + process.stdout.write(`${computeNextPlanId(root)} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/get-next-task-id.cjs b/.agents/skills/st-full-workflow/scripts/get-next-task-id.cjs new file mode 100644 index 0000000..9529a46 --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/get-next-task-id.cjs @@ -0,0 +1,303 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/get-next-task-id.ts +var get_next_task_id_exports = {}; +__export(get_next_task_id_exports, { + main: () => main +}); +module.exports = __toCommonJS(get_next_task_id_exports); + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/task-scan.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var computeNextTaskId = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs4.existsSync(tasksDir)) return 1; + let entries; + try { + entries = fs4.readdirSync(tasksDir, { withFileTypes: true }); + } catch (_err) { + return 1; + } + if (entries.length === 0) return 1; + const ids = entries.filter((e) => e.isFile() && e.name.endsWith(".md")).flatMap((e) => { + const filePath = path4.join(tasksDir, e.name); + try { + const content = fs4.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + return id === null ? [] : [id]; + } catch (_err) { + return []; + } + }); + const max = ids.reduce((acc, id) => Math.max(acc, id), 0); + return max + 1; +}; + +// src/skill-scripts/get-next-task-id.ts +var main = () => { + const inputId = process.argv[2]; + if (!inputId) { + process.stderr.write("Error: Plan ID or path is required\n"); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`Error: Plan "${inputId}" not found or invalid. +`); + process.exit(1); + } + process.stdout.write(`${computeNextTaskId(resolved.planDir)} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-full-workflow/scripts/route-task-execution.cjs b/.agents/skills/st-full-workflow/scripts/route-task-execution.cjs new file mode 100755 index 0000000..97ef1eb --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/route-task-execution.cjs @@ -0,0 +1,3138 @@ +#!/usr/bin/env node +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// src/skill-scripts/route-task-execution.ts +var fs5 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/execution-routing.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); +var EXECUTION_ROUTING_SECTION = "execution_routing"; +var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0; +var validateTarget = (profileName, index, raw, supportedHarnesses, errors) => { + const label = `profile "${profileName}" models[${index}]`; + if (!isPlainObject2(raw)) { + errors.push(`${label} must be a mapping with an exact "model" string.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "model" && key !== "harness" && key !== "reasoning_effort") { + errors.push(`${label} has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.model)) { + errors.push(`${label} requires a non-empty exact "model" string.`); + return null; + } + const target = { model: raw.model }; + if ("harness" in raw) { + if (!isNonEmptyString(raw.harness)) { + errors.push(`${label} "harness" must be a non-empty string when provided.`); + return null; + } + if (!supportedHarnesses.includes(raw.harness)) { + errors.push(`${label} harness "${raw.harness}" is not a supported harness.`); + return null; + } + target.harness = raw.harness; + } + if ("reasoning_effort" in raw) { + if (!isNonEmptyString(raw.reasoning_effort)) { + errors.push(`${label} "reasoning_effort" must be a non-empty string when provided.`); + return null; + } + target.reasoning_effort = raw.reasoning_effort; + } + return target; +}; +var validateProfile = (name, raw, supportedHarnesses, errors) => { + if (!isPlainObject2(raw)) { + errors.push(`profile "${name}" must be a mapping with "description" and "models".`); + return null; + } + if ("resolver" in raw) { + errors.push( + `profile "${name}" configures a per-profile resolver; only the single top-level "resolver" is supported.` + ); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "description" && key !== "models") { + errors.push(`profile "${name}" has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.description)) { + errors.push(`profile "${name}" requires a non-empty LLM-facing "description".`); + return null; + } + if (!Array.isArray(raw.models) || raw.models.length === 0) { + errors.push(`profile "${name}" requires a non-empty ordered "models" array.`); + return null; + } + const targets = []; + for (let i = 0; i < raw.models.length; i += 1) { + const target = validateTarget(name, i, raw.models[i], supportedHarnesses, errors); + if (!target) return null; + targets.push(target); + } + return { name, description: raw.description.trim(), targets }; +}; +var loadRoutingConfig = (strikethrooRoot, supportedHarnesses) => { + const configPath = path4.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs4.readFileSync(configPath, "utf8"); + } catch { + return { kind: "no-config" }; + } + if (!hasYamlContent(contents)) return { kind: "disabled" }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) return { kind: "disabled" }; + if (!isPlainObject2(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[EXECUTION_ROUTING_SECTION]; + if (section === null || section === void 0) return { kind: "disabled" }; + const errors = []; + if (!isPlainObject2(section)) { + return { + kind: "invalid", + errors: [`config.yaml "${EXECUTION_ROUTING_SECTION}" must be a YAML mapping.`] + }; + } + for (const key of Object.keys(section)) { + if (key !== "enabled" && key !== "allow_external_harness_execution" && key !== "profiles" && key !== "resolver") { + errors.push(`${EXECUTION_ROUTING_SECTION} has unknown key "${key}".`); + } + } + if ("allow_external_harness_execution" in section && typeof section.allow_external_harness_execution !== "boolean") { + errors.push( + `${EXECUTION_ROUTING_SECTION} "allow_external_harness_execution" must be true or false.` + ); + } + if ("enabled" in section) { + if (typeof section.enabled !== "boolean") { + errors.push(`${EXECUTION_ROUTING_SECTION} "enabled" must be true or false.`); + return { kind: "invalid", errors }; + } + if (!section.enabled) + return errors.length > 0 ? { kind: "invalid", errors } : { kind: "disabled" }; + } + const rawProfiles = "profiles" in section && section.profiles == null ? {} : section.profiles; + if (!("profiles" in section) || !isPlainObject2(rawProfiles)) { + errors.push(`${EXECUTION_ROUTING_SECTION} requires a "profiles" mapping.`); + return { kind: "invalid", errors }; + } + const profiles = []; + for (const [name, rawProfile] of Object.entries(rawProfiles)) { + const profile = validateProfile(name, rawProfile, supportedHarnesses, errors); + if (profile) profiles.push(profile); + } + let resolverScript; + if ("resolver" in section) { + const resolver = section.resolver; + if (!isPlainObject2(resolver) || !isNonEmptyString(resolver.script)) { + errors.push('resolver must be a mapping with a non-empty "script" path.'); + } else { + for (const key of Object.keys(resolver)) { + if (key !== "script") errors.push(`resolver has unknown key "${key}".`); + } + resolverScript = resolver.script; + } + } + if (errors.length > 0) return { kind: "invalid", errors }; + if (profiles.length === 0) return { kind: "disabled" }; + const config = { + allowExternalHarnessExecution: section.allow_external_harness_execution === true, + profiles + }; + if (resolverScript !== void 0) config.resolverScript = resolverScript; + return { kind: "config", config }; +}; +var validateAssignments = (rawMap, taskIds, profileNames) => { + const errors = []; + if (!isPlainObject2(rawMap)) { + return { + kind: "invalid", + errors: ["assignment map must be a JSON object of task-ID to profile-name."] + }; + } + const assignments = /* @__PURE__ */ new Map(); + const known = new Set(taskIds); + for (const [rawId, rawProfile] of Object.entries(rawMap)) { + if (!/^\d+$/.test(rawId.trim())) { + errors.push(`assignment key "${rawId}" is not a task ID.`); + continue; + } + const id = parseInt(rawId, 10); + if (assignments.has(id)) { + errors.push(`task ${id} is assigned more than once.`); + continue; + } + if (!known.has(id)) { + errors.push(`assignment references unknown task ID ${id}.`); + continue; + } + if (typeof rawProfile !== "string" || !profileNames.includes(rawProfile)) { + errors.push(`task ${id} is assigned unknown profile "${String(rawProfile)}".`); + continue; + } + assignments.set(id, rawProfile); + } + for (const id of taskIds) { + if (!assignments.has(id)) errors.push(`task ${id} has no profile assignment.`); + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "assignments", assignments }; +}; +var writeExecutionProfileFrontmatter = (taskMarkdown, profile) => { + const match = taskMarkdown.match(/^(---\r?\n)([\s\S]*?)(\r?\n---)/); + if (!match) throw new Error("missing frontmatter"); + const opening = match[1]; + const frontmatter = match[2]; + const closing = match[3]; + if (opening === void 0 || frontmatter === void 0 || closing === void 0) { + throw new Error("missing frontmatter"); + } + const eol = frontmatter.includes("\r\n") ? "\r\n" : "\n"; + const lines = frontmatter.split(/\r?\n/); + const kept = []; + let inExecutionBlock = false; + for (const line of lines) { + if (/^execution_profile\s*:/.test(line)) continue; + if (/^execution\s*:/.test(line)) { + inExecutionBlock = true; + continue; + } + if (inExecutionBlock && /^[ \t]/.test(line)) continue; + inExecutionBlock = false; + kept.push(line); + } + const newFrontmatter = [...kept, `execution_profile: ${JSON.stringify(profile)}`].join(eol); + return `${opening}${newFrontmatter}${closing}${taskMarkdown.slice(match[0].length)}`; +}; + +// src/skill-scripts/route-task-execution.ts +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var usage = () => emit( + { + kind: "infrastructure-failure", + detail: "Usage: route-task-execution.cjs profiles | route-task-execution.cjs apply " + }, + 2 +); +var readTaskDocuments = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + let entries; + try { + entries = fs5.readdirSync(tasksDir, { withFileTypes: true }); + } catch { + return { kind: "invalid", errors: [`no tasks directory at ${tasksDir}.`] }; + } + const errors = []; + const tasks = []; + const seen = /* @__PURE__ */ new Map(); + const taskFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".md")).map((e) => e.name).sort(); + for (const name of taskFiles) { + const entry = { name }; + const file = path5.join(tasksDir, entry.name); + const content = fs5.readFileSync(file, "utf8"); + const id = extractPlanId(content, file); + if (id === null) { + errors.push(`task file ${entry.name} has no integer id in its frontmatter.`); + continue; + } + const duplicate = seen.get(id); + if (duplicate !== void 0) { + errors.push(`task id ${id} appears in both ${duplicate} and ${entry.name}.`); + continue; + } + seen.set(id, entry.name); + tasks.push({ id, file, content }); + } + if (tasks.length === 0) errors.push("plan has no task files to route."); + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "tasks", tasks }; +}; +var main = () => { + const [mode, planIdArg, ...rest] = process.argv.slice(2); + if (mode !== "profiles" && mode !== "apply" || !planIdArg) usage(); + const resolved = resolvePlan(planIdArg); + if (!resolved) { + emit({ kind: "infrastructure-failure", detail: `plan "${planIdArg}" did not resolve.` }, 2); + return; + } + const configResult = loadRoutingConfig(resolved.strikethrooRoot, SUPPORTED_HARNESSES); + if (configResult.kind === "invalid") { + emit({ kind: "invalid-config", errors: configResult.errors }, 1); + } + if (configResult.kind !== "config") { + emit({ kind: configResult.kind }, 0); + return; + } + const config = configResult.config; + if (mode === "profiles") { + emit( + { + kind: "profiles", + profiles: config.profiles.map((profile) => ({ + name: profile.name, + description: profile.description, + targetCount: profile.targets.length + })), + customResolver: config.resolverScript !== void 0 + }, + 0 + ); + } + const [assignmentFile, ...extraArgs] = rest; + if (!assignmentFile || extraArgs.length > 0) usage(); + const documents = readTaskDocuments(resolved.planDir); + if (documents.kind === "invalid") { + emit({ kind: "invalid-tasks", errors: documents.errors }, 1); + return; + } + let rawMap; + try { + rawMap = JSON.parse(fs5.readFileSync(assignmentFile, "utf8")); + } catch (error) { + emit( + { + kind: "invalid-assignments", + errors: [ + `could not read assignment map: ${error instanceof Error ? error.message : String(error)}` + ] + }, + 1 + ); + return; + } + const assignmentResult = validateAssignments( + rawMap, + documents.tasks.map((task) => task.id), + config.profiles.map((profile) => profile.name) + ); + if (assignmentResult.kind === "invalid") { + emit({ kind: "invalid-assignments", errors: assignmentResult.errors }, 1); + return; + } + const staged = []; + for (const task of documents.tasks) { + const profile = assignmentResult.assignments.get(task.id); + if (!profile) { + emit({ kind: "routing-failure", detail: `no profile assigned for task ${task.id}.` }, 1); + return; + } + let next; + try { + next = writeExecutionProfileFrontmatter(task.content, profile); + } catch (error) { + emit( + { + kind: "routing-failure", + detail: `task ${task.id} (${path5.basename(task.file)}): ${error instanceof Error ? error.message : String(error)}` + }, + 1 + ); + return; + } + if (!next.includes(`execution_profile: ${JSON.stringify(profile)}`)) { + emit( + { kind: "routing-failure", detail: `task ${task.id} would not verify after routing.` }, + 1 + ); + return; + } + staged.push({ task, next, profile }); + } + const written = []; + try { + for (const { task, next } of staged) { + fs5.writeFileSync(task.file, next); + written.push(task); + } + for (const { task, next } of staged) { + const reread = fs5.readFileSync(task.file, "utf8"); + if (reread !== next) { + throw new Error(`task ${task.id} failed post-write verification.`); + } + } + } catch (error) { + for (const task of written) { + try { + fs5.writeFileSync(task.file, task.content); + } catch { + } + } + emit( + { + kind: "infrastructure-failure", + detail: `routing aborted and rolled back: ${error instanceof Error ? error.message : String(error)}` + }, + 2 + ); + return; + } + emit( + { + kind: "routed", + tasks: staged.map(({ task, profile }) => ({ + id: task.id, + file: task.file, + executionProfile: profile + })) + }, + 0 + ); +}; +try { + main(); +} catch (error) { + emit( + { + kind: "infrastructure-failure", + detail: `execution routing failed: ${error instanceof Error ? error.message : String(error)}` + }, + 2 + ); +} +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-generate-tasks/SKILL.md b/.agents/skills/st-generate-tasks/SKILL.md new file mode 100644 index 0000000..f87678d --- /dev/null +++ b/.agents/skills/st-generate-tasks/SKILL.md @@ -0,0 +1,218 @@ +--- +name: st-generate-tasks +description: Use when the user asks to decompose, break down, or generate tasks for an existing Strikethroo plan ID in this repository — triggers include generate tasks, break down the plan, decompose plan, create the task blueprint. Do not use to create a new plan, to execute tasks, or for generic project planning outside Strikethroo. +--- + +# st-generate-tasks + +## Inputs + +The user supplies the numeric plan ID conversationally. + +## Operating Procedure + +### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +### 2. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, stop and ask the user to confirm the plan ID. +Do not guess a different ID. + +### 3. Load project context + +Read these files, in order: + +- `/config/STRIKETHROO.md` — project and directory conventions. +- The plan body at the path returned by step 2 — the contract for + what tasks must exist. +- `/config/templates/TASK_TEMPLATE.md` — the schema every task file + must match. +- `/config/shared/anti-rationalization.md` — apply in step 4. + +### 4. Analyze and decompose the plan + +Read the entire plan. Identify all concrete deliverables **explicitly stated**. +Decompose each deliverable into atomic tasks only when genuinely needed. + +**Task minimization (mandatory):** + +- Create only the minimum number of tasks necessary. Target a 20–30% + reduction from comprehensive lists by questioning the necessity of each + candidate. +- Every task corresponds to an explicit requirement, never a nice-to-have, a + "best practice", or future extensibility the plan does not mention. +- Each task has a unique, non-overlapping purpose. +- Keep error handling inside the task that owns the behavior it guards. + +Apply `/config/shared/anti-rationalization.md` to this rationalization table: + +| You catch yourself thinking… | The binding rule | +| --- | --- | +| "One extra task won't hurt." | It violates the 20–30% minimization target. Every task traces to an **explicitly stated** deliverable or it does not exist. | +| "This edge case deserves its own task." | Fold it into the task that owns the behavior. Do not split trivially small operations into separate units. | +| "I'll add a test suite to be safe." | Comprehensive tests for trivial functionality are gold-plating. Follow the test philosophy — meaningful tests only. | +| "Future extensibility justifies this task." | YAGNI. The plan does not mention it, so it is not a task. | + +### 5. Apply granularity and skill rules + +Each task must be: + +- **Single-purpose** — one clear deliverable. +- **Atomic** — cannot be meaningfully split further. +- **Skill-specific** — executable by an agent with 1–2 technical skills. +- **Verifiable** — has explicit acceptance criteria that include at least one + concrete, runnable verification step (a command plus its expected output, or + another observable signal). Never settle for a vague "works correctly". + +Infer skills in kebab-case from the task's technical requirements. Use one +skill for a single-domain task and two for complementary domains, such as +`["api-endpoints", "database"]`. Three or more means the task must be broken +down further. + +### 6. Test philosophy: "write a few tests, mostly integration" + +**Write tests for:** + +- Custom business logic and algorithms. +- Critical user workflows and data transformations. +- Edge cases and error conditions in core functionality. +- Integration points between components. +- Complex validation or calculation logic. + +**Do not write tests for:** + +- Third-party library and framework functionality. +- Simple CRUD without custom logic. +- Trivial getters/setters and static configuration. +- Obvious functionality that would break immediately if incorrect. + +Combine related test scenarios into one task ("Test user authentication flow", +not separate tasks for login, logout, and validation). Favor integration and +critical-path coverage over per-method unit tests. Never create one test task +per CRUD operation. + +Copy these rules into the "Implementation Notes" of every test task you +generate. + +### 7. Dependency analysis + +Task B depends on task A when B requires A's output or artifacts, modifies +code created by A, or tests functionality implemented by A. Record it as a +**hard dependency** when B cannot start before A completes and as a **soft +dependency** when B merely runs better after A. Validate that the final +dependency graph is acyclic. + +### 8. Complexity analysis + +For every candidate task, assign a `complexity_score` (integer 1–10) before +writing any file. Read `references/complexity-rubric.md` before scoring; it +defines the four dimensions each band is judged on. Then apply these rules: + +- Score ≥ 8 → decompose further; do not emit as-is. +- Score 6–7 → sharpen or split; do not emit without an explicit reason. +- Vague acceptance criteria → sharpen them into a concrete, runnable + verification step. +- Trivially small adjacent tasks → merge them. + +**Loop-back rule:** after applying split, sharpen, or merge, re-run dependency +analysis and re-score the adjusted tasks. Repeat no more than three times. If +complexity is still unresolved after three passes, stop and surface the +blocker to the user. + +### 9. Allocate task IDs + +Run `scripts/get-next-task-id.cjs ` once for the first available task +ID, then allocate the rest by incrementing in-process. Use the unpadded +integer in the task frontmatter `id` field and the zero-padded form in the +filename. The slug derives from a short task title: lowercase, alphanumeric +and hyphens only, collapsed, trimmed. + +### 10. Emit the task files + +Write each task to: + +``` +/plans//tasks/{padded-id}--{slug}.md +``` + +Each file must conform to `/config/templates/TASK_TEMPLATE.md`. Add +`complexity_notes` only when the score needs justification. Never write +`execution_profile`; the routing helper writes it. + +Fill every body section with task-specific content. Place detailed +implementation guidance inside a `
` block under "Implementation +Notes", written so a non-thinking LLM could execute the task from that +section alone. + +### 11. Validation checklist + +Before declaring task generation complete, verify: + +- Every **explicitly stated** deliverable in the plan is covered by a task. +- No two tasks overlap in purpose. +- Dependencies form an acyclic graph, with no orphan or circular references. +- Groups are consistent across the plan. +- After writing the task files, run + `scripts/validate-plan-blueprint.cjs complexityScoresValid`. Stop + unless it prints `yes`; if it prints `no`, run + `scripts/validate-plan-blueprint.cjs invalidComplexityTasks` to see + which files are missing, non-integer, or out-of-range, fix them, and re-run. + +### 12. Route task execution + +Read `/config/hooks/TASK_EXECUTION_ROUTING.md` and follow its +instructions together with this procedure: + +1. Run `scripts/route-task-execution.cjs profiles `. On `no-config` + or `disabled`, routing is off; skip the remaining routing steps and + continue. On `invalid-config`, stop and surface the errors to the user; do + not generate the blueprint. +2. Assign every task in the plan's `tasks/` directory exactly one configured + profile name. Classify the tasks generated in this run from the content + already in your context. If the plan carried task files from an earlier + generation run, read those files to classify them. +3. Write the complete task-ID-to-profile mapping as a JSON object to a + temporary file, for example `{"1": "routine", "2": "demanding"}`. +4. Run `scripts/route-task-execution.cjs apply `. + Target selection happens later at task dispatch, never during generation. +5. On `routed`, delete the temporary mapping file and continue. On any failure + result (`invalid-assignments`, `invalid-tasks`, `routing-failure`, + `infrastructure-failure`), stop and surface the JSON errors to the user. + Never continue to blueprint generation with partially routed tasks. + +Never hand-write a concrete execution target into task frontmatter or task +bodies. + +### 13. Run the POST_TASK_GENERATION_ALL hook + +Read `/config/hooks/POST_TASK_GENERATION_ALL.md` and follow its +instructions, using `/config/templates/BLUEPRINT_TEMPLATE.md` for the +Execution Blueprint structure. Run the hook only after routing succeeded or +reported routing off. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. + +## Failure Modes + +- **User declines to clarify a blocking ambiguity.** Mark the affected tasks + with `status: "needs-clarification"` and document the open question in the + task's "Implementation Notes". Do not invent answers. +- **A helper script fails unexpectedly.** Surface stderr to the user and + stop — do not fall back to manual ID allocation or path discovery. diff --git a/.agents/skills/st-generate-tasks/references/complexity-rubric.md b/.agents/skills/st-generate-tasks/references/complexity-rubric.md new file mode 100644 index 0000000..fee2699 --- /dev/null +++ b/.agents/skills/st-generate-tasks/references/complexity-rubric.md @@ -0,0 +1,8 @@ +# Complexity rubric + +| Score | Skill breadth | Acceptance-criteria clarity | Integration surface | Decomposition depth | +| --- | --- | --- | --- | --- | +| 1–3 | One well-known skill | Criteria are concrete and observable | None or a single file/module | No further split possible | +| 4–5 | One primary skill plus a familiar adjacent skill | Criteria are clear with few edge cases | One component or API boundary | Already atomic | +| 6–7 | Two distinct skills, or one skill with ambiguous requirements | Criteria need clarification or have multiple edge cases | Multiple components or contracts | Could still be split | +| 8–10 | Three or more skills, or cross-cutting design decisions | Criteria are vague, unknown, or depend on unresolved choices | Wide integration surface or external systems | Must be decomposed further | diff --git a/.agents/skills/st-generate-tasks/scripts/check-for-updates.cjs b/.agents/skills/st-generate-tasks/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-generate-tasks/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs b/.agents/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-generate-tasks/scripts/get-next-task-id.cjs b/.agents/skills/st-generate-tasks/scripts/get-next-task-id.cjs new file mode 100644 index 0000000..9529a46 --- /dev/null +++ b/.agents/skills/st-generate-tasks/scripts/get-next-task-id.cjs @@ -0,0 +1,303 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/get-next-task-id.ts +var get_next_task_id_exports = {}; +__export(get_next_task_id_exports, { + main: () => main +}); +module.exports = __toCommonJS(get_next_task_id_exports); + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/task-scan.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var computeNextTaskId = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs4.existsSync(tasksDir)) return 1; + let entries; + try { + entries = fs4.readdirSync(tasksDir, { withFileTypes: true }); + } catch (_err) { + return 1; + } + if (entries.length === 0) return 1; + const ids = entries.filter((e) => e.isFile() && e.name.endsWith(".md")).flatMap((e) => { + const filePath = path4.join(tasksDir, e.name); + try { + const content = fs4.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + return id === null ? [] : [id]; + } catch (_err) { + return []; + } + }); + const max = ids.reduce((acc, id) => Math.max(acc, id), 0); + return max + 1; +}; + +// src/skill-scripts/get-next-task-id.ts +var main = () => { + const inputId = process.argv[2]; + if (!inputId) { + process.stderr.write("Error: Plan ID or path is required\n"); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`Error: Plan "${inputId}" not found or invalid. +`); + process.exit(1); + } + process.stdout.write(`${computeNextTaskId(resolved.planDir)} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-generate-tasks/scripts/route-task-execution.cjs b/.agents/skills/st-generate-tasks/scripts/route-task-execution.cjs new file mode 100755 index 0000000..97ef1eb --- /dev/null +++ b/.agents/skills/st-generate-tasks/scripts/route-task-execution.cjs @@ -0,0 +1,3138 @@ +#!/usr/bin/env node +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// src/skill-scripts/route-task-execution.ts +var fs5 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/execution-routing.ts +var fs4 = __toESM(require("fs")); +var path4 = __toESM(require("path")); + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +function pick(object, keys) { + const result = {}; + for (const key of keys) if (object[key] !== void 0) result[key] = object[key]; + return result; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var DEFAULT_SNIPPET_OPTIONS = { + maxLength: 79, + indent: 1, + linesBefore: 3, + linesAfter: 2 +}; +function getLine(buffer, lineStart, lineEnd, position, maxLineLength) { + let head = ""; + let tail = ""; + const maxHalfLength = Math.floor(maxLineLength / 2) - 1; + if (position - lineStart > maxHalfLength) { + head = " ... "; + lineStart = position - maxHalfLength + head.length; + } + if (lineEnd - position > maxHalfLength) { + tail = " ..."; + lineEnd = position + maxHalfLength - tail.length; + } + return { + str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail, + pos: position - lineStart + head.length + }; +} +function padStart(string, max) { + return " ".repeat(Math.max(max - string.length, 0)) + string; +} +function makeSnippet(mark, options) { + if (!mark.buffer) return null; + const opts = { + ...DEFAULT_SNIPPET_OPTIONS, + ...options + }; + const re = /\r?\n|\r|\0/g; + const lineStarts = [0]; + const lineEnds = []; + let match; + let foundLineNo = -1; + while (match = re.exec(mark.buffer)) { + lineEnds.push(match.index); + lineStarts.push(match.index + match[0].length); + if (mark.position <= match.index && foundLineNo < 0) foundLineNo = lineStarts.length - 2; + } + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; + let result = ""; + const lineNoLength = Math.min(mark.line + opts.linesAfter, lineEnds.length).toString().length; + const maxLineLength = opts.maxLength - (opts.indent + lineNoLength + 3); + for (let i = 1; i <= opts.linesBefore; i++) { + if (foundLineNo - i < 0) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength); + result = `${" ".repeat(opts.indent)}${padStart((mark.line - i + 1).toString(), lineNoLength)} | ${line2.str} +${result}`; + } + const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + 1).toString(), lineNoLength)} | ${line.str} +`; + result += `${"-".repeat(opts.indent + lineNoLength + 3 + line.pos)}^ +`; + for (let i = 1; i <= opts.linesAfter; i++) { + if (foundLineNo + i >= lineEnds.length) break; + const line2 = getLine(mark.buffer, lineStarts[foundLineNo + i], lineEnds[foundLineNo + i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]), maxLineLength); + result += `${" ".repeat(opts.indent)}${padStart((mark.line + i + 1).toString(), lineNoLength)} | ${line2.str} +`; + } + return result.replace(/\n$/, ""); +} +function formatError(exception, compact) { + let where = ""; + if (!exception.mark) return exception.reason; + if (exception.mark.name) where += `in "${exception.mark.name}" `; + where += `(${exception.mark.line + 1}:${exception.mark.column + 1})`; + if (!compact && exception.mark.snippet) where += ` + +${exception.mark.snippet}`; + return `${exception.reason} ${where}`; +} +var YAMLException = class YAMLException2 extends Error { + reason; + mark; + /** + * Optional `mark` contains source snippet data. Usually, use + * {@link YAMLException.throwAt} instead of passing it directly. + */ + constructor(reason, mark) { + super(); + this.name = "YAMLException"; + this.reason = reason; + this.mark = mark; + this.message = formatError(this, false); + if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); + } + /** + * Returns the formatted error, omitting the source snippet in compact mode. + */ + toString(compact) { + return `${this.name}: ${formatError(this, compact)}`; + } + /** + * Builds a YAMLException with a source snippet and throws it. `source` is + * the raw input text; `position` is an offset into it. + */ + static throwAt(source, position, message, filename = "") { + let line = 0; + let lineStart = 0; + for (let index = 0; index < position; index++) { + const ch = source.charCodeAt(index); + if (ch === 10) { + line++; + lineStart = index + 1; + } else if (ch === 13) { + line++; + if (source.charCodeAt(index + 1) === 10) index++; + lineStart = index + 1; + } + } + const mark = { + name: filename, + buffer: source, + position, + line, + column: position - lineStart + }; + mark.snippet = makeSnippet(mark); + throw new YAMLException2(message, mark); + } +}; +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +var NO_RANGE$3 = -1; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +function charFromCodepoint(c) { + if (c <= 65535) return String.fromCharCode(c); + return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320); +} +function fromHexCode$1(c) { + if (c >= 48 && c <= 57) return c - 48; + return (c | 32) - 97 + 10; +} +function escapedHexLen$1(c) { + if (c === 120) return 2; + if (c === 117) return 4; + return 8; +} +function skipFoldedBreaks(input, position, end) { + let breaks = 0; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10) { + breaks++; + position++; + } else if (ch === 13) { + breaks++; + position++; + if (input.charCodeAt(position) === 10) position++; + } else if (ch === 32 || ch === 9) position++; + else break; + } + return { + position, + breaks + }; +} +function foldedBreaks(count) { + if (count === 1) return " "; + return "\n".repeat(count - 1); +} +function getPlainValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, captureEnd); +} +function getSingleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 39) { + result += input.slice(captureStart, position) + "'"; + position += 2; + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getDoubleQuotedValue(input, start, end) { + let result = ""; + let position = start; + let captureStart = start; + let captureEnd = start; + while (position < end) { + const ch = input.charCodeAt(position); + if (ch === 92) { + result += input.slice(captureStart, position); + position++; + const escaped = input.charCodeAt(position); + if (escaped === 10 || escaped === 13) position = skipFoldedBreaks(input, position, end).position; + else if (escaped < 256 && simpleEscapeCheck[escaped]) { + result += simpleEscapeMap[escaped]; + position++; + } else { + let hexLength = escapedHexLen$1(escaped); + let hexResult = 0; + for (; hexLength > 0; hexLength--) { + position++; + const digit = fromHexCode$1(input.charCodeAt(position)); + hexResult = (hexResult << 4) + digit; + } + result += charFromCodepoint(hexResult); + position++; + } + captureStart = captureEnd = position; + } else if (ch === 10 || ch === 13) { + result += input.slice(captureStart, captureEnd); + const fold = skipFoldedBreaks(input, position, end); + result += foldedBreaks(fold.breaks); + position = captureStart = captureEnd = fold.position; + } else { + position++; + if (ch !== 32 && ch !== 9) captureEnd = position; + } + } + return result + input.slice(captureStart, end); +} +function getBlockValue(input, start, end, indent, chomping, folded) { + const textIndent = indent < 0 ? 0 : indent; + const region = input.slice(start, end).replace(/\r\n?/g, "\n"); + const lines = region === "" ? [] : (region.endsWith("\n") ? region.slice(0, -1) : region).split("\n"); + let result = ""; + let didReadContent = false; + let emptyLines = 0; + let atMoreIndented = false; + for (const line of lines) { + let column = 0; + while (column < textIndent && line.charCodeAt(column) === 32) column++; + if (indent < 0 || column >= line.length) { + emptyLines++; + continue; + } + const content = line.slice(textIndent); + const first = content.charCodeAt(0); + if (folded) if (first === 32 || first === 9) { + atMoreIndented = true; + result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + } else if (atMoreIndented) { + atMoreIndented = false; + result += "\n".repeat(emptyLines + 1); + } else if (emptyLines === 0) { + if (didReadContent) result += " "; + } else result += "\n".repeat(emptyLines); + else result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + result += content; + didReadContent = true; + emptyLines = 0; + } + if (chomping === CHOMPING_MODE.KEEP) result += "\n".repeat(didReadContent ? 1 + emptyLines : emptyLines); + else if (chomping !== CHOMPING_MODE.STRIP) { + if (didReadContent) result += "\n"; + } + return result; +} +function getScalarValue(input, scalar) { + if (scalar.valueStart === NO_RANGE$3) return ""; + const { valueStart, valueEnd } = scalar; + if (scalar.fast) return input.slice(valueStart, valueEnd); + switch (scalar.style) { + case SCALAR_STYLE.SINGLE_QUOTED: + return getSingleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.DOUBLE_QUOTED: + return getDoubleQuotedValue(input, valueStart, valueEnd); + case SCALAR_STYLE.LITERAL_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, false); + case SCALAR_STYLE.FOLDED_BLOCK: + return getBlockValue(input, valueStart, valueEnd, scalar.indent, scalar.chomping, true); + default: + return getPlainValue(input, valueStart, valueEnd); + } +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +function tagNameFull(rawTag, tagHandlers) { + if (rawTag.startsWith("!<") && rawTag.endsWith(">")) return decodeURIComponent(rawTag.slice(2, -1)); + const handleEnd = rawTag.indexOf("!", 1); + const handle = handleEnd === -1 ? "!" : rawTag.slice(0, handleEnd + 1); + const prefix = tagHandlers?.[handle] ?? DEFAULT_TAG_HANDLERS[handle] ?? handle; + return decodeURIComponent(prefix) + decodeURIComponent(rawTag.slice(handle.length)); +} +var NO_RANGE$2 = -1; +var MERGE_TAG_NAME = "tag:yaml.org,2002:merge"; +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +function eventPosition$1(event) { + if ("tagStart" in event && event.tagStart !== NO_RANGE$2) return event.tagStart; + if ("anchorStart" in event && event.anchorStart !== NO_RANGE$2) return event.anchorStart; + if ("valueStart" in event && event.valueStart !== NO_RANGE$2) return event.valueStart; + if ("start" in event) return event.start; + return 0; +} +function throwError$1(state, message) { + YAMLException.throwAt(state.source, state.position, message, state.filename); +} +function finalizeCollection(state, position, tag, carrier) { + try { + return tag.finalize(carrier); + } catch (error) { + if (error instanceof YAMLException) throw error; + YAMLException.throwAt(state.source, position, error instanceof Error ? error.message : String(error), state.filename); + } +} +function constructScalar(state, event) { + const source = getScalarValue(state.source, event); + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + const strTag2 = state.schema.defaultScalarTag; + if (rawTag !== "") { + if (rawTag === "!") return { + value: source, + tag: strTag2 + }; + const tagName = tagNameFull(rawTag, state.tagHandlers); + const scalarTag = state.schema.lookupScalarTag(tagName); + if (scalarTag) { + const result = scalarTag.resolve(source, true, tagName); + if (result === NOT_RESOLVED) throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + return { + value: result, + tag: scalarTag + }; + } + const collectionTagDef = state.schema.lookupMappingTag(tagName) ?? state.schema.lookupSequenceTag(tagName); + if (collectionTagDef) { + if (source !== "") throwError$1(state, `cannot resolve a node with !<${tagName}> explicit tag`); + const carrier = collectionTagDef.create(tagName); + return { + value: collectionTagDef.carrierIsResult ? carrier : finalizeCollection(state, state.position, collectionTagDef, carrier), + tag: collectionTagDef + }; + } + throwError$1(state, `unknown scalar tag !<${tagName}>`); + } + if (event.style === SCALAR_STYLE.PLAIN) return state.schema.resolveImplicitScalarTag(source); + return { + value: strTag2.resolve(source, false, strTag2.tagName), + tag: strTag2 + }; +} +function collectionTagName(state, event, defaultTagName) { + const rawTag = event.tagStart === NO_RANGE$2 ? "" : state.source.slice(event.tagStart, event.tagEnd); + return rawTag === "" || rawTag === "!" ? defaultTagName : tagNameFull(rawTag, state.tagHandlers); +} +function isMappingTag(tag) { + return tag.nodeKind === "mapping"; +} +function chargeMergeWork(state) { + state.totalMergeKeys++; + if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`); +} +function mergeKeys(state, frame, source, sourceTag) { + chargeMergeWork(state); + for (const sourceKey of sourceTag.keys(source)) { + chargeMergeWork(state); + if (frame.tag.has(frame.value, sourceKey)) continue; + const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey)); + if (err) throwError$1(state, err); + frame.overridable ??= /* @__PURE__ */ new Set(); + frame.overridable.add(sourceKey); + } +} +function mergeSource(state, frame, source, sourceTag) { + state.position = frame.keyPosition; + if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag); + else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) { + if (source.length > 100) throwError$1(state, "abnormal merge sequence size"); + for (const element of source) { + const elementTag = state.nodeTags.get(element); + if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); + mergeKeys(state, frame, element, elementTag); + } + } else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable"); +} +function addMappingValue(state, frame, key, value, tag) { + state.position = frame.keyPosition; + if (frame.keyIsMerge) { + mergeSource(state, frame, value, tag); + return; + } + if (!state.json && frame.tag.has(frame.value, key) && !frame.overridable?.has(key)) throwError$1(state, "duplicated mapping key"); + const err = frame.tag.addPair(frame.value, key, value); + if (err) throwError$1(state, err); + frame.overridable?.delete(key); +} +function addValue(state, value, tag) { + const frame = state.frames[state.frames.length - 1]; + if (frame.kind === "document") { + frame.value = value; + frame.hasValue = true; + } else if (frame.kind === "sequence") { + if (isMappingTag(tag)) state.nodeTags.set(value, tag); + const err = frame.tag.addItem(frame.value, value, frame.index++); + if (err) throwError$1(state, err); + } else if (frame.hasKey) { + const key = frame.key; + frame.key = void 0; + frame.hasKey = false; + addMappingValue(state, frame, key, value, tag); + } else { + frame.key = value; + frame.keyPosition = state.position; + frame.hasKey = true; + frame.keyIsMerge = tag.tagName === MERGE_TAG_NAME; + } +} +function storeAnchor(state, event, value, tag, isValueFinal) { + if (event.anchorStart !== NO_RANGE$2) { + const anchor = { + value, + tag, + isValueFinal + }; + state.anchors.set(state.source.slice(event.anchorStart, event.anchorEnd), anchor); + return anchor; + } + return null; +} +function constructFromEvents(events, options) { + const state = { + ...DEFAULT_CONSTRUCTOR_OPTIONS, + ...options, + events, + documents: [], + eventIndex: 0, + position: 0, + frames: [], + anchors: /* @__PURE__ */ new Map(), + nodeTags: /* @__PURE__ */ new Map(), + tagHandlers: /* @__PURE__ */ Object.create(null), + totalMergeKeys: 0, + aliasCount: 0 + }; + while (state.eventIndex < state.events.length) { + const event = state.events[state.eventIndex++]; + state.position = eventPosition$1(event); + switch (event.type) { + case EVENT_ID.DOCUMENT: + state.anchors = /* @__PURE__ */ new Map(); + state.nodeTags = /* @__PURE__ */ new Map(); + state.aliasCount = 0; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + for (const directive of event.directives) if (directive.kind === "tag") state.tagHandlers[directive.handle] = directive.prefix; + state.frames.push({ + kind: "document", + position: state.position, + value: void 0, + hasValue: false + }); + break; + case EVENT_ID.SCALAR: { + const { value, tag } = constructScalar(state, event); + storeAnchor(state, event, value, tag, true); + addValue(state, value, tag); + break; + } + case EVENT_ID.SEQUENCE: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:seq"); + const tag = state.schema.lookupSequenceTag(tagName); + if (!tag) throwError$1(state, `unknown sequence tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "sequence", + position: state.position, + value, + tag, + anchor, + index: 0 + }); + break; + } + case EVENT_ID.MAPPING: { + const tagName = collectionTagName(state, event, "tag:yaml.org,2002:map"); + const tag = state.schema.lookupMappingTag(tagName); + if (!tag) throwError$1(state, `unknown mapping tag !<${tagName}>`); + const value = tag.create(tagName); + const anchor = storeAnchor(state, event, value, tag, tag.carrierIsResult); + state.frames.push({ + kind: "mapping", + position: state.position, + value, + tag, + anchor, + key: void 0, + keyPosition: state.position, + hasKey: false, + keyIsMerge: false, + overridable: null + }); + break; + } + case EVENT_ID.ALIAS: { + if (state.maxAliases !== -1 && ++state.aliasCount > state.maxAliases) throwError$1(state, `aliases exceeded maxAliases (${state.maxAliases})`); + const name = state.source.slice(event.anchorStart, event.anchorEnd); + const anchor = state.anchors.get(name); + if (!anchor) throwError$1(state, `unidentified alias "${name}"`); + if (!anchor.isValueFinal) throwError$1(state, `recursive alias "${name}" is not supported for tag ${anchor.tag.tagName} because it uses finalize()`); + addValue(state, anchor.value, anchor.tag); + break; + } + case EVENT_ID.POP: { + const frame = state.frames.pop(); + if (frame.kind === "mapping" && frame.hasKey) { + state.position = frame.keyPosition; + throwError$1(state, "incomplete mapping pair in event stream"); + } + if (frame.kind === "document") state.documents.push(frame.value); + else { + const value = frame.tag.carrierIsResult ? frame.value : finalizeCollection(state, frame.position, frame.tag, frame.value); + if (frame.anchor) { + frame.anchor.value = value; + frame.anchor.isValueFinal = true; + } + addValue(state, value, frame.tag); + } + break; + } + } + } + return state.documents; +} +var NO_RANGE$1 = -1; +var HAS_OWN = Object.prototype.hasOwnProperty; +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +function addDocumentEvent(state, explicitStart, explicitEnd) { + state.events.push({ + type: EVENT_ID.DOCUMENT, + explicitStart, + explicitEnd, + directives: state.directives + }); +} +function addSequenceEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.SEQUENCE, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function addMappingEvent(state, start, anchorStart, anchorEnd, tagStart, tagEnd, style) { + state.events.push({ + type: EVENT_ID.MAPPING, + start, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style + }); +} +function insertFlowPairMappingEvent(state, snapshot) { + state.events.splice(snapshot.eventsLength, 0, { + type: EVENT_ID.MAPPING, + start: snapshot.position, + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1, + style: COLLECTION_STYLE.FLOW + }); +} +function addScalarEvent(state, valueStart, valueEnd, anchorStart, anchorEnd, tagStart, tagEnd, style, chomping = CHOMPING_MODE.CLIP, indent = -1, fast = false) { + state.events.push({ + type: EVENT_ID.SCALAR, + valueStart, + valueEnd, + anchorStart, + anchorEnd, + tagStart, + tagEnd, + style, + chomping, + indent, + fast + }); +} +function addAliasEvent(state, anchorStart, anchorEnd) { + state.events.push({ + type: EVENT_ID.ALIAS, + anchorStart, + anchorEnd + }); +} +function addPopEvent(state) { + state.events.push({ type: EVENT_ID.POP }); +} +function addEmptyScalarEvent(state) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, NO_RANGE$1, SCALAR_STYLE.PLAIN); +} +function emptyProperties() { + return { + anchorStart: NO_RANGE$1, + anchorEnd: NO_RANGE$1, + tagStart: NO_RANGE$1, + tagEnd: NO_RANGE$1 + }; +} +function snapshotState(state) { + return { + position: state.position, + line: state.line, + lineStart: state.lineStart, + lineIndent: state.lineIndent, + firstTabInLine: state.firstTabInLine, + eventsLength: state.events.length + }; +} +function restoreState(state, snapshot) { + state.position = snapshot.position; + state.line = snapshot.line; + state.lineStart = snapshot.lineStart; + state.lineIndent = snapshot.lineIndent; + state.firstTabInLine = snapshot.firstTabInLine; + state.events.length = snapshot.eventsLength; +} +function throwError(state, message) { + YAMLException.throwAt(state.input.slice(0, state.length), state.position, message, state.filename); +} +function isEol(c) { + return c === 10 || c === 13; +} +function isWhiteSpace(c) { + return c === 9 || c === 32; +} +function isWsOrEol(c) { + return isWhiteSpace(c) || isEol(c); +} +function isWsOrEolOrEnd(c) { + return c === 0 || isWsOrEol(c); +} +function isFlowIndicator(c) { + return c === 44 || c === 91 || c === 93 || c === 123 || c === 125; +} +function fromDecimalCode(c) { + return c >= 48 && c <= 57 ? c - 48 : -1; +} +function fromHexCode(c) { + if (c >= 48 && c <= 57) return c - 48; + const lc = c | 32; + if (lc >= 97 && lc <= 102) return lc - 97 + 10; + return -1; +} +function escapedHexLen(c) { + if (c === 120) return 2; + if (c === 117) return 4; + if (c === 85) return 8; + return 0; +} +function isSimpleEscape(c) { + return c === 48 || c === 97 || c === 98 || c === 116 || c === 9 || c === 110 || c === 118 || c === 102 || c === 114 || c === 101 || c === 32 || c === 34 || c === 47 || c === 92 || c === 78 || c === 95 || c === 76 || c === 80; +} +function consumeLineBreak(state) { + if (state.input.charCodeAt(state.position) === 10) state.position++; + else { + state.position++; + if (state.input.charCodeAt(state.position) === 10) state.position++; + } + state.line++; + state.lineStart = state.position; + state.lineIndent = 0; + state.firstTabInLine = -1; +} +function skipSeparationSpace(state, allowComments) { + let lineBreaks = 0; + let ch = state.input.charCodeAt(state.position); + let hasSeparation = state.position === state.lineStart || isWsOrEol(state.input.charCodeAt(state.position - 1)); + while (ch !== 0) { + while (isWhiteSpace(ch)) { + hasSeparation = true; + if (ch === 9 && state.firstTabInLine === -1) state.firstTabInLine = state.position; + ch = state.input.charCodeAt(++state.position); + } + if (allowComments && hasSeparation && ch === 35) do + ch = state.input.charCodeAt(++state.position); + while (!isEol(ch) && ch !== 0); + if (!isEol(ch)) break; + consumeLineBreak(state); + lineBreaks++; + hasSeparation = true; + ch = state.input.charCodeAt(state.position); + while (ch === 32) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } + return lineBreaks; +} +function testDocumentSeparator(state, position = state.position) { + const ch = state.input.charCodeAt(position); + if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(position + 1) && ch === state.input.charCodeAt(position + 2)) { + const following = state.input.charCodeAt(position + 3); + return following === 0 || isWsOrEol(following); + } + return false; +} +function skipByteOrderMark(state) { + if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) { + state.position++; + state.lineStart = state.position; + } +} +function testDocumentBoundary(state) { + if (state.position !== state.lineStart) return false; + if (testDocumentSeparator(state)) return true; + if (state.input.charCodeAt(state.position) !== 65279) return false; + const snapshot = snapshotState(state); + skipByteOrderMark(state); + skipSeparationSpace(state, true); + const ch = state.input.charCodeAt(state.position); + const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state)); + restoreState(state, snapshot); + return result; +} +function skipUntilLineEnd(state) { + let ch = state.input.charCodeAt(state.position); + while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position); +} +function checkPrintable(state, start, end) { + if (PATTERN_NON_PRINTABLE.test(state.input.slice(start, end))) throwError(state, "the stream contains non-printable characters"); +} +function readTagProperty(state, props, inFlow) { + if (state.input.charCodeAt(state.position) !== 33) return false; + if (props.tagStart !== NO_RANGE$1) throwError(state, "duplication of a tag property"); + const start = state.position; + let isVerbatim = false; + let isNamed = false; + let tagHandle = "!"; + let ch = state.input.charCodeAt(++state.position); + if (ch === 60) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + } else if (ch === 33) { + isNamed = true; + tagHandle = "!!"; + ch = state.input.charCodeAt(++state.position); + } + let suffixStart = state.position; + let tagName; + if (isVerbatim) { + while (ch !== 0 && ch !== 62) ch = state.input.charCodeAt(++state.position); + if (ch !== 62) throwError(state, "unexpected end of the stream within a verbatim tag"); + tagName = state.input.slice(suffixStart, state.position); + state.position++; + } else { + while (ch !== 0 && !isWsOrEol(ch) && !(inFlow && isFlowIndicator(ch))) { + if (ch === 33) if (!isNamed) { + tagHandle = state.input.slice(suffixStart - 1, state.position + 1); + if (!PATTERN_TAG_HANDLE.test(tagHandle)) throwError(state, "named tag handle cannot contain such characters"); + isNamed = true; + suffixStart = state.position + 1; + } else throwError(state, "tag suffix cannot contain exclamation marks"); + ch = state.input.charCodeAt(++state.position); + } + tagName = state.input.slice(suffixStart, state.position); + if (PATTERN_FLOW_INDICATORS.test(tagName)) throwError(state, "tag suffix cannot contain flow indicator characters"); + } + if (tagName && !(isVerbatim ? PATTERN_TAG_URI.test(tagName) : PATTERN_TAG_SUFFIX.test(tagName))) throwError(state, `tag name cannot contain such characters: ${tagName}`); + if (!isVerbatim && tagHandle !== "!" && tagHandle !== "!!" && !HAS_OWN.call(state.tagHandlers, tagHandle)) throwError(state, `undeclared tag handle "${tagHandle}"`); + props.tagStart = start; + props.tagEnd = state.position; + return true; +} +function readAnchorProperty(state, props) { + if (state.input.charCodeAt(state.position) !== 38) return false; + if (props.anchorStart !== NO_RANGE$1) throwError(state, "duplication of an anchor property"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an anchor node must contain at least one character"); + props.anchorStart = start; + props.anchorEnd = state.position; + return true; +} +function readAlias(state, props) { + if (state.input.charCodeAt(state.position) !== 42) return false; + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) throwError(state, "alias node should not have any properties"); + state.position++; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position)) && !isFlowIndicator(state.input.charCodeAt(state.position))) state.position++; + if (state.position === start) throwError(state, "name of an alias node must contain at least one character"); + addAliasEvent(state, start, state.position); + return true; +} +function readFlowScalarBreak(state, nodeIndent) { + skipSeparationSpace(state, false); + if (state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readSingleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 39) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 39) { + if (state.input.charCodeAt(state.position + 1) === 39) { + simple = false; + state.position += 2; + continue; + } + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.SINGLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a single quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a single quoted scalar"); +} +function readDoubleQuotedScalar(state, nodeIndent, props) { + if (state.input.charCodeAt(state.position) !== 34) return false; + state.position++; + const start = state.position; + let simple = true; + while (state.input.charCodeAt(state.position) !== 0) { + const ch = state.input.charCodeAt(state.position); + if (ch === 34) { + const end = state.position; + state.position++; + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.DOUBLE_QUOTED, CHOMPING_MODE.CLIP, -1, simple); + return true; + } + if (ch === 92) { + simple = false; + const escaped = state.input.charCodeAt(++state.position); + if (isEol(escaped)) readFlowScalarBreak(state, nodeIndent); + else if (isSimpleEscape(escaped)) state.position++; + else { + let hexLength = escapedHexLen(escaped); + if (hexLength === 0) throwError(state, "unknown escape sequence"); + while (hexLength-- > 0) { + state.position++; + if (fromHexCode(state.input.charCodeAt(state.position)) < 0) throwError(state, "expected hexadecimal character"); + } + state.position++; + } + } else if (isEol(ch)) { + simple = false; + readFlowScalarBreak(state, nodeIndent); + } else if (state.position === state.lineStart && testDocumentSeparator(state)) throwError(state, "unexpected end of the document within a double quoted scalar"); + else if (ch !== 9 && ch < 32) throwError(state, "expected valid JSON character"); + else state.position++; + } + throwError(state, "unexpected end of the stream within a double quoted scalar"); +} +function readBlockScalar(state, parentIndent, props) { + const ch = state.input.charCodeAt(state.position); + let chomping = CHOMPING_MODE.CLIP; + let indent = -1; + let detectedIndent = false; + if (ch !== 124 && ch !== 62) return false; + const style = ch === 124 ? SCALAR_STYLE.LITERAL_BLOCK : SCALAR_STYLE.FOLDED_BLOCK; + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + const current = state.input.charCodeAt(state.position); + const digit = fromDecimalCode(current); + if (current === 43 || current === 45) { + if (chomping !== CHOMPING_MODE.CLIP) throwError(state, "repeat of a chomping mode identifier"); + chomping = current === 43 ? CHOMPING_MODE.KEEP : CHOMPING_MODE.STRIP; + state.position++; + } else if (digit >= 0) { + if (digit === 0) throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one"); + if (detectedIndent) throwError(state, "repeat of an indentation width identifier"); + indent = parentIndent + digit - 1; + detectedIndent = true; + state.position++; + } else break; + } + let hadWhitespace = false; + while (isWhiteSpace(state.input.charCodeAt(state.position))) { + hadWhitespace = true; + state.position++; + } + if (hadWhitespace && state.input.charCodeAt(state.position) === 35) skipUntilLineEnd(state); + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + else if (state.input.charCodeAt(state.position) !== 0) throwError(state, "a line break is expected"); + let contentIndent = detectedIndent ? indent : -1; + let maxLeadingIndent = 0; + const valueStart = state.position; + let valueEnd = state.position; + while (state.input.charCodeAt(state.position) !== 0) { + const linePosition = state.position; + let column = 0; + while (state.input.charCodeAt(linePosition + column) === 32) column++; + const first = state.input.charCodeAt(linePosition + column); + if (first === 0) { + if (contentIndent >= 0) { + if (column > contentIndent) valueEnd = linePosition + column; + } else if (column > 0) valueEnd = linePosition + column; + break; + } + if (testDocumentBoundary(state)) break; + if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column); + if (!detectedIndent && contentIndent === -1 && !isEol(first)) { + if (first === 9 && column < parentIndent) { + state.position = linePosition + column; + throwError(state, "tab characters must not be used in indentation"); + } + if (column < maxLeadingIndent) { + state.position = linePosition + column; + throwError(state, "bad indentation of a mapping entry"); + } + } + if (contentIndent === -1 && first !== 0 && !isEol(first) && column < parentIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + if (!detectedIndent && first !== 0 && !isEol(first) && contentIndent === -1) contentIndent = column; + const requiredIndent = contentIndent === -1 ? parentIndent + 1 : contentIndent; + if (first !== 0 && !isEol(first) && column < requiredIndent) { + state.lineIndent = column; + state.position = linePosition + column; + break; + } + skipUntilLineEnd(state); + valueEnd = state.position; + if (isEol(state.input.charCodeAt(state.position))) { + consumeLineBreak(state); + valueEnd = state.position; + } + } + checkPrintable(state, valueStart, valueEnd); + addScalarEvent(state, valueStart, valueEnd, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, style, chomping, contentIndent); + return true; +} +function canStartPlainScalar(state, nodeContext) { + const ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + if (ch === 0 || isWsOrEol(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96 || inFlow && isFlowIndicator(ch)) return false; + if (ch === 63 || ch === 45) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) return false; + } + return true; +} +function readPlainScalar(state, nodeIndent, nodeContext, props) { + if (!canStartPlainScalar(state, nodeContext)) return false; + const start = state.position; + let end = state.position; + let ch = state.input.charCodeAt(state.position); + const inFlow = nodeContext === CONTEXT_FLOW_IN; + let multiline = false; + while (ch !== 0) { + if (testDocumentBoundary(state)) break; + if (ch === 58) { + const following = state.input.charCodeAt(state.position + 1); + if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break; + } else if (ch === 35) { + if (isWsOrEol(state.input.charCodeAt(state.position - 1))) break; + } else if (inFlow && isFlowIndicator(ch)) break; + else if (isEol(ch)) { + const savedPosition = state.position; + const savedLine = state.line; + const savedLineStart = state.lineStart; + const savedLineIndent = state.lineIndent; + skipSeparationSpace(state, false); + if (state.lineIndent >= nodeIndent) { + multiline = true; + ch = state.input.charCodeAt(state.position); + continue; + } + state.position = savedPosition; + state.line = savedLine; + state.lineStart = savedLineStart; + state.lineIndent = savedLineIndent; + break; + } + if (!isWhiteSpace(ch)) end = state.position + 1; + ch = state.input.charCodeAt(++state.position); + } + if (end === start) return false; + checkPrintable(state, start, end); + addScalarEvent(state, start, end, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN, CHOMPING_MODE.CLIP, -1, !multiline); + return true; +} +function skipFlowSeparationSpace(state, nodeIndent) { + const startLine = state.line; + skipSeparationSpace(state, true); + if (state.line > startLine && state.lineIndent < nodeIndent || state.firstTabInLine !== -1 && state.lineIndent < nodeIndent) throwError(state, "deficient indentation"); +} +function readFlowCollection(state, nodeIndent, props) { + const ch = state.input.charCodeAt(state.position); + const isMapping = ch === 123; + const start = state.position; + let readNext = true; + if (ch !== 91 && ch !== 123) return false; + const terminator = isMapping ? 125 : 93; + if (isMapping) addMappingEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + else addSequenceEvent(state, start, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.FLOW); + state.position++; + while (state.input.charCodeAt(state.position) !== 0) { + skipFlowSeparationSpace(state, nodeIndent); + let ch2 = state.input.charCodeAt(state.position); + if (ch2 === terminator) { + state.position++; + addPopEvent(state); + return true; + } else if (!readNext) throwError(state, "missed comma between flow collection entries"); + else if (ch2 === 44) throwError(state, "expected the node content, but found ','"); + let isPair = false; + let isExplicitPair = false; + if (ch2 === 63 && isWsOrEol(state.input.charCodeAt(state.position + 1))) { + isPair = isExplicitPair = true; + state.position += 1; + skipFlowSeparationSpace(state, nodeIndent); + } + const entryLine = state.line; + const entryStart = snapshotState(state); + const keyWasRead = parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + skipFlowSeparationSpace(state, nodeIndent); + ch2 = state.input.charCodeAt(state.position); + if ((isMapping || isExplicitPair || state.line === entryLine) && ch2 === 58) { + isPair = true; + state.position++; + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + } else if (!keyWasRead) addEmptyScalarEvent(state); + if (!parseNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)) addEmptyScalarEvent(state); + skipFlowSeparationSpace(state, nodeIndent); + if (!isMapping) addPopEvent(state); + } else if (isMapping && isPair) { + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + } else if (isMapping) addEmptyScalarEvent(state); + else if (isPair) { + insertFlowPairMappingEvent(state, entryStart); + if (!keyWasRead) addEmptyScalarEvent(state); + addEmptyScalarEvent(state); + addPopEvent(state); + } + ch2 = state.input.charCodeAt(state.position); + if (ch2 === 44) { + readNext = true; + state.position++; + } else readNext = false; + } + throwError(state, "unexpected end of the stream within a flow collection"); +} +function readBlockSequence(state, nodeIndent, props) { + if (state.firstTabInLine !== -1 || state.input.charCodeAt(state.position) !== 45 || !isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) return false; + addSequenceEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + while (state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) { + if (state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const entryLine = state.line; + state.position++; + const hadBreak = skipSeparationSpace(state, true) > 0; + if (state.firstTabInLine !== -1 && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + if (hadBreak && state.lineIndent <= nodeIndent) addEmptyScalarEvent(state); + else parseNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + skipSeparationSpace(state, true); + if (state.lineIndent < nodeIndent || state.position >= state.length) break; + if (state.lineIndent > nodeIndent) throwError(state, "bad indentation of a sequence entry"); + if (state.line === entryLine && state.input.charCodeAt(state.position) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 1))) throwError(state, "bad indentation of a sequence entry"); + } + addPopEvent(state); + return true; +} +function readBlockMapping(state, nodeIndent, flowIndent, props) { + let atExplicitKey = false; + let detected = false; + let mappingOpened = false; + let pendingExplicitKey = false; + if (state.firstTabInLine !== -1) return false; + let ch = state.input.charCodeAt(state.position); + while (ch !== 0) { + if (!atExplicitKey && state.firstTabInLine !== -1) { + state.position = state.firstTabInLine; + throwError(state, "tab characters must not be used in indentation"); + } + const following = state.input.charCodeAt(state.position + 1); + const entryLine = state.line; + if ((ch === 63 || ch === 58) && isWsOrEolOrEnd(following)) { + if (!mappingOpened) { + addMappingEvent(state, state.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + } + if (ch === 63) { + if (atExplicitKey) addEmptyScalarEvent(state); + detected = true; + atExplicitKey = true; + } else if (atExplicitKey) atExplicitKey = false; + else { + addEmptyScalarEvent(state); + detected = true; + atExplicitKey = false; + } + state.position += 1; + pendingExplicitKey = true; + } else { + if (atExplicitKey) { + addEmptyScalarEvent(state); + atExplicitKey = false; + } + const beforeKey = snapshotState(state); + if (!parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) break; + if (state.line === entryLine) { + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + if (ch === 58) { + ch = state.input.charCodeAt(++state.position); + if (!isWsOrEolOrEnd(ch)) throwError(state, "a whitespace character is expected after the key-value separator within a block mapping"); + if (!mappingOpened) { + restoreState(state, beforeKey); + addMappingEvent(state, beforeKey.position, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, COLLECTION_STYLE.BLOCK); + mappingOpened = true; + parseNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true); + ch = state.input.charCodeAt(state.position); + while (isWhiteSpace(ch)) ch = state.input.charCodeAt(++state.position); + state.position++; + } + detected = true; + atExplicitKey = false; + pendingExplicitKey = false; + } else if (detected) throwError(state, "expected ':' after a mapping key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } else if (detected) throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key"); + else { + if (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1) { + restoreState(state, beforeKey); + return false; + } + return true; + } + } + if (parseNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, pendingExplicitKey)) pendingExplicitKey = false; + if (!atExplicitKey) { + if (pendingExplicitKey) { + addEmptyScalarEvent(state); + pendingExplicitKey = false; + } + } + skipSeparationSpace(state, true); + ch = state.input.charCodeAt(state.position); + if ((state.line === entryLine || state.lineIndent > nodeIndent) && ch !== 0) throwError(state, "bad indentation of a mapping entry"); + else if (state.lineIndent < nodeIndent) break; + } + if (!detected) return false; + if (atExplicitKey) addEmptyScalarEvent(state); + if (mappingOpened) addPopEvent(state); + return true; +} +function parseNode(state, parentIndent, nodeContext, allowToSeek, allowCompact, allowPropertyMapping = true) { + if (state.depth >= state.maxDepth) throwError(state, `nesting exceeded maxDepth (${state.maxDepth})`); + state.depth++; + let indentStatus = 1; + let atNewLine = false; + let hasContent = false; + let propertyStart = null; + const props = emptyProperties(); + let allowBlockScalars = nodeContext === CONTEXT_BLOCK_OUT || nodeContext === CONTEXT_BLOCK_IN; + let allowBlockCollections = allowBlockScalars; + const allowBlockStyles = allowBlockScalars; + if (allowToSeek && skipSeparationSpace(state, true)) { + atNewLine = true; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } + if (indentStatus === 1) while (true) { + const ch = state.input.charCodeAt(state.position); + const propertyState = snapshotState(state); + if (atNewLine && indentStatus !== 1 && (ch === 33 || ch === 38)) break; + if (atNewLine && allowBlockStyles && (props.tagStart !== NO_RANGE$1 || props.anchorStart !== NO_RANGE$1) && (ch === 33 || ch === 38)) { + const fallbackState = snapshotState(state); + const flowIndent = parentIndent + 1; + if (readBlockMapping(state, state.position - state.lineStart, flowIndent, props) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) { + state.depth--; + return true; + } + restoreState(state, fallbackState); + } + if (atNewLine && (ch === 33 && props.tagStart !== NO_RANGE$1 || ch === 38 && props.anchorStart !== NO_RANGE$1)) break; + if (!readTagProperty(state, props, nodeContext === CONTEXT_FLOW_IN) && !readAnchorProperty(state, props)) break; + if (propertyStart === null) propertyStart = propertyState; + if (skipSeparationSpace(state, true)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + if (state.lineIndent > parentIndent) indentStatus = 1; + else if (state.lineIndent === parentIndent) indentStatus = 0; + else indentStatus = -1; + } else allowBlockCollections = false; + } + if (allowBlockCollections) allowBlockCollections = atNewLine || allowCompact; + if (indentStatus === 1 || nodeContext === CONTEXT_BLOCK_OUT) { + const flowIndent = nodeContext === CONTEXT_FLOW_IN || nodeContext === CONTEXT_FLOW_OUT ? parentIndent : parentIndent + 1; + const blockIndent = state.position - state.lineStart; + if (indentStatus === 1) if (allowBlockCollections && (readBlockSequence(state, blockIndent, props) || readBlockMapping(state, blockIndent, flowIndent, props)) || readFlowCollection(state, flowIndent, props)) hasContent = true; + else { + const ch = state.input.charCodeAt(state.position); + if (propertyStart !== null && allowPropertyMapping && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62) { + const fallbackState = snapshotState(state); + const propertyIndent = propertyStart.position - propertyStart.lineStart; + restoreState(state, propertyStart); + if (readBlockMapping(state, propertyIndent, flowIndent, emptyProperties()) && state.events[fallbackState.eventsLength]?.type === EVENT_ID.MAPPING) hasContent = true; + else restoreState(state, fallbackState); + } + if (!hasContent && (allowBlockScalars && readBlockScalar(state, flowIndent, props) || readSingleQuotedScalar(state, flowIndent, props) || readDoubleQuotedScalar(state, flowIndent, props) || readAlias(state, props) || readPlainScalar(state, flowIndent, nodeContext, props))) hasContent = true; + } + else if (indentStatus === 0) hasContent = allowBlockCollections && readBlockSequence(state, blockIndent, props); + } + allowBlockScalars = allowBlockScalars && !hasContent; + if (!hasContent && (props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1 || allowBlockScalars)) { + addScalarEvent(state, NO_RANGE$1, NO_RANGE$1, props.anchorStart, props.anchorEnd, props.tagStart, props.tagEnd, SCALAR_STYLE.PLAIN); + hasContent = true; + } + state.depth--; + return hasContent || props.anchorStart !== NO_RANGE$1 || props.tagStart !== NO_RANGE$1; +} +function readDirective(state) { + if (state.lineIndent > 0 || state.input.charCodeAt(state.position) !== 37) return false; + state.position++; + const nameStart = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + const name = state.input.slice(nameStart, state.position); + const args = []; + if (name.length === 0) throwError(state, "directive name must not be less than one character in length"); + while (state.input.charCodeAt(state.position) !== 0 && !isEol(state.input.charCodeAt(state.position))) { + while (isWhiteSpace(state.input.charCodeAt(state.position))) state.position++; + if (state.input.charCodeAt(state.position) === 35 || isEol(state.input.charCodeAt(state.position)) || state.input.charCodeAt(state.position) === 0) break; + const start = state.position; + while (state.input.charCodeAt(state.position) !== 0 && !isWsOrEol(state.input.charCodeAt(state.position))) state.position++; + args.push(state.input.slice(start, state.position)); + } + if (isEol(state.input.charCodeAt(state.position))) consumeLineBreak(state); + if (name === "YAML") { + if (state.directives.some((directive) => directive.kind === "yaml")) throwError(state, "duplication of %YAML directive"); + if (args.length !== 1) throwError(state, "YAML directive accepts exactly one argument"); + const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + if (match === null) throwError(state, "ill-formed argument of the YAML directive"); + if (parseInt(match[1], 10) !== 1) throwError(state, "unacceptable YAML version of the document"); + state.directives.push({ + kind: "yaml", + version: args[0] + }); + } else if (name === "TAG") { + if (args.length !== 2) throwError(state, "TAG directive accepts exactly two arguments"); + const [handle, prefix] = args; + if (!PATTERN_TAG_HANDLE.test(handle)) throwError(state, "ill-formed tag handle (first argument) of the TAG directive"); + if (HAS_OWN.call(state.tagHandlers, handle)) throwError(state, `there is a previously declared suffix for "${handle}" tag handle`); + if (!PATTERN_TAG_PREFIX.test(prefix)) throwError(state, "ill-formed tag prefix (second argument) of the TAG directive"); + state.tagHandlers[handle] = prefix; + state.directives.push({ + kind: "tag", + handle, + prefix + }); + } + return true; +} +function readDocument(state) { + state.directives = []; + state.tagHandlers = /* @__PURE__ */ Object.create(null); + let hasDirectives = false; + skipSeparationSpace(state, true); + while (readDirective(state)) { + hasDirectives = true; + skipSeparationSpace(state, true); + } + let explicitStart = false; + let explicitEnd = false; + let allowCompact = true; + if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45 && isWsOrEolOrEnd(state.input.charCodeAt(state.position + 3))) { + explicitStart = true; + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + allowCompact = state.line > markerLine; + } else if (hasDirectives) throwError(state, "directives end mark is expected"); + const documentEventIndex = state.events.length; + if (!explicitStart && state.position === state.lineStart && state.input.charCodeAt(state.position) === 46 && testDocumentSeparator(state)) { + state.position += 3; + skipSeparationSpace(state, true); + return; + } + addDocumentEvent(state, explicitStart, false); + if (!parseNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, allowCompact, allowCompact)) addEmptyScalarEvent(state); + skipSeparationSpace(state, true); + if (state.position === state.lineStart && testDocumentSeparator(state)) { + explicitEnd = state.input.charCodeAt(state.position) === 46; + if (explicitEnd) { + const markerLine = state.line; + state.position += 3; + skipSeparationSpace(state, true); + if (state.line === markerLine && state.position < state.length) throwError(state, "end of the stream or a document separator is expected"); + } + } + const documentEvent = state.events[documentEventIndex]; + if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd; + addPopEvent(state); + if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected"); +} +function parseEvents(input, options) { + const length = input.length; + const state = { + ...DEFAULT_PARSER_OPTIONS, + ...options, + input: `${input}\0`, + length, + position: 0, + line: 0, + lineStart: 0, + lineIndent: 0, + firstTabInLine: -1, + depth: 0, + directives: [], + tagHandlers: /* @__PURE__ */ Object.create(null), + events: [] + }; + const nullpos = input.indexOf("\0"); + if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename); + while (state.position < state.length) { + skipByteOrderMark(state); + skipSeparationSpace(state, true); + if (state.position >= state.length) break; + const documentStart = state.position; + readDocument(state); + if (state.position === documentStart) + throwError(state, "can not read a document"); + } + return state.events; +} +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function loadDocuments(input, options = {}) { + const opts = { + ...DEFAULT_LOAD_OPTIONS, + ...options + }; + const source = String(input); + const PARSER_OPT_KEYS = Object.keys(DEFAULT_PARSER_OPTIONS); + const CONSTRUCTOR_OPT_KEYS = Object.keys(DEFAULT_CONSTRUCTOR_OPTIONS); + return constructFromEvents(parseEvents(source, pick(opts, PARSER_OPT_KEYS)), { + ...pick(opts, CONSTRUCTOR_OPT_KEYS), + source + }); +} +function load(input, options) { + const documents = loadDocuments(input, options); + if (documents.length === 0) throw new YAMLException("expected a document, but the input is empty"); + if (documents.length === 1) return documents[0]; + throw new YAMLException("expected a single document in the stream, but found more"); +} +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; +var hasYamlContent = (block) => block.split(/\r?\n/).some((line) => { + const trimmed = line.trim(); + return trimmed !== "" && !trimmed.startsWith("#"); +}); + +// src/skill-scripts/shared/execution-routing.ts +var WORKSPACE_CONFIG_RELPATH = path4.join("config", "config.yaml"); +var EXECUTION_ROUTING_SECTION = "execution_routing"; +var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value); +var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0; +var validateTarget = (profileName, index, raw, supportedHarnesses, errors) => { + const label = `profile "${profileName}" models[${index}]`; + if (!isPlainObject2(raw)) { + errors.push(`${label} must be a mapping with an exact "model" string.`); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "model" && key !== "harness" && key !== "reasoning_effort") { + errors.push(`${label} has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.model)) { + errors.push(`${label} requires a non-empty exact "model" string.`); + return null; + } + const target = { model: raw.model }; + if ("harness" in raw) { + if (!isNonEmptyString(raw.harness)) { + errors.push(`${label} "harness" must be a non-empty string when provided.`); + return null; + } + if (!supportedHarnesses.includes(raw.harness)) { + errors.push(`${label} harness "${raw.harness}" is not a supported harness.`); + return null; + } + target.harness = raw.harness; + } + if ("reasoning_effort" in raw) { + if (!isNonEmptyString(raw.reasoning_effort)) { + errors.push(`${label} "reasoning_effort" must be a non-empty string when provided.`); + return null; + } + target.reasoning_effort = raw.reasoning_effort; + } + return target; +}; +var validateProfile = (name, raw, supportedHarnesses, errors) => { + if (!isPlainObject2(raw)) { + errors.push(`profile "${name}" must be a mapping with "description" and "models".`); + return null; + } + if ("resolver" in raw) { + errors.push( + `profile "${name}" configures a per-profile resolver; only the single top-level "resolver" is supported.` + ); + return null; + } + for (const key of Object.keys(raw)) { + if (key !== "description" && key !== "models") { + errors.push(`profile "${name}" has unknown key "${key}".`); + return null; + } + } + if (!isNonEmptyString(raw.description)) { + errors.push(`profile "${name}" requires a non-empty LLM-facing "description".`); + return null; + } + if (!Array.isArray(raw.models) || raw.models.length === 0) { + errors.push(`profile "${name}" requires a non-empty ordered "models" array.`); + return null; + } + const targets = []; + for (let i = 0; i < raw.models.length; i += 1) { + const target = validateTarget(name, i, raw.models[i], supportedHarnesses, errors); + if (!target) return null; + targets.push(target); + } + return { name, description: raw.description.trim(), targets }; +}; +var loadRoutingConfig = (strikethrooRoot, supportedHarnesses) => { + const configPath = path4.join(strikethrooRoot, WORKSPACE_CONFIG_RELPATH); + let contents; + try { + contents = fs4.readFileSync(configPath, "utf8"); + } catch { + return { kind: "no-config" }; + } + if (!hasYamlContent(contents)) return { kind: "disabled" }; + let document; + try { + document = load(contents); + } catch (error) { + return { + kind: "invalid", + errors: [ + `config.yaml is not valid YAML: ${error instanceof Error ? error.message : String(error)}` + ] + }; + } + if (document === null || document === void 0) return { kind: "disabled" }; + if (!isPlainObject2(document)) { + return { kind: "invalid", errors: ["config.yaml must be a YAML mapping."] }; + } + const section = document[EXECUTION_ROUTING_SECTION]; + if (section === null || section === void 0) return { kind: "disabled" }; + const errors = []; + if (!isPlainObject2(section)) { + return { + kind: "invalid", + errors: [`config.yaml "${EXECUTION_ROUTING_SECTION}" must be a YAML mapping.`] + }; + } + for (const key of Object.keys(section)) { + if (key !== "enabled" && key !== "allow_external_harness_execution" && key !== "profiles" && key !== "resolver") { + errors.push(`${EXECUTION_ROUTING_SECTION} has unknown key "${key}".`); + } + } + if ("allow_external_harness_execution" in section && typeof section.allow_external_harness_execution !== "boolean") { + errors.push( + `${EXECUTION_ROUTING_SECTION} "allow_external_harness_execution" must be true or false.` + ); + } + if ("enabled" in section) { + if (typeof section.enabled !== "boolean") { + errors.push(`${EXECUTION_ROUTING_SECTION} "enabled" must be true or false.`); + return { kind: "invalid", errors }; + } + if (!section.enabled) + return errors.length > 0 ? { kind: "invalid", errors } : { kind: "disabled" }; + } + const rawProfiles = "profiles" in section && section.profiles == null ? {} : section.profiles; + if (!("profiles" in section) || !isPlainObject2(rawProfiles)) { + errors.push(`${EXECUTION_ROUTING_SECTION} requires a "profiles" mapping.`); + return { kind: "invalid", errors }; + } + const profiles = []; + for (const [name, rawProfile] of Object.entries(rawProfiles)) { + const profile = validateProfile(name, rawProfile, supportedHarnesses, errors); + if (profile) profiles.push(profile); + } + let resolverScript; + if ("resolver" in section) { + const resolver = section.resolver; + if (!isPlainObject2(resolver) || !isNonEmptyString(resolver.script)) { + errors.push('resolver must be a mapping with a non-empty "script" path.'); + } else { + for (const key of Object.keys(resolver)) { + if (key !== "script") errors.push(`resolver has unknown key "${key}".`); + } + resolverScript = resolver.script; + } + } + if (errors.length > 0) return { kind: "invalid", errors }; + if (profiles.length === 0) return { kind: "disabled" }; + const config = { + allowExternalHarnessExecution: section.allow_external_harness_execution === true, + profiles + }; + if (resolverScript !== void 0) config.resolverScript = resolverScript; + return { kind: "config", config }; +}; +var validateAssignments = (rawMap, taskIds, profileNames) => { + const errors = []; + if (!isPlainObject2(rawMap)) { + return { + kind: "invalid", + errors: ["assignment map must be a JSON object of task-ID to profile-name."] + }; + } + const assignments = /* @__PURE__ */ new Map(); + const known = new Set(taskIds); + for (const [rawId, rawProfile] of Object.entries(rawMap)) { + if (!/^\d+$/.test(rawId.trim())) { + errors.push(`assignment key "${rawId}" is not a task ID.`); + continue; + } + const id = parseInt(rawId, 10); + if (assignments.has(id)) { + errors.push(`task ${id} is assigned more than once.`); + continue; + } + if (!known.has(id)) { + errors.push(`assignment references unknown task ID ${id}.`); + continue; + } + if (typeof rawProfile !== "string" || !profileNames.includes(rawProfile)) { + errors.push(`task ${id} is assigned unknown profile "${String(rawProfile)}".`); + continue; + } + assignments.set(id, rawProfile); + } + for (const id of taskIds) { + if (!assignments.has(id)) errors.push(`task ${id} has no profile assignment.`); + } + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "assignments", assignments }; +}; +var writeExecutionProfileFrontmatter = (taskMarkdown, profile) => { + const match = taskMarkdown.match(/^(---\r?\n)([\s\S]*?)(\r?\n---)/); + if (!match) throw new Error("missing frontmatter"); + const opening = match[1]; + const frontmatter = match[2]; + const closing = match[3]; + if (opening === void 0 || frontmatter === void 0 || closing === void 0) { + throw new Error("missing frontmatter"); + } + const eol = frontmatter.includes("\r\n") ? "\r\n" : "\n"; + const lines = frontmatter.split(/\r?\n/); + const kept = []; + let inExecutionBlock = false; + for (const line of lines) { + if (/^execution_profile\s*:/.test(line)) continue; + if (/^execution\s*:/.test(line)) { + inExecutionBlock = true; + continue; + } + if (inExecutionBlock && /^[ \t]/.test(line)) continue; + inExecutionBlock = false; + kept.push(line); + } + const newFrontmatter = [...kept, `execution_profile: ${JSON.stringify(profile)}`].join(eol); + return `${opening}${newFrontmatter}${closing}${taskMarkdown.slice(match[0].length)}`; +}; + +// src/skill-scripts/route-task-execution.ts +var emit = (result, exitCode) => { + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(exitCode); +}; +var usage = () => emit( + { + kind: "infrastructure-failure", + detail: "Usage: route-task-execution.cjs profiles | route-task-execution.cjs apply " + }, + 2 +); +var readTaskDocuments = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + let entries; + try { + entries = fs5.readdirSync(tasksDir, { withFileTypes: true }); + } catch { + return { kind: "invalid", errors: [`no tasks directory at ${tasksDir}.`] }; + } + const errors = []; + const tasks = []; + const seen = /* @__PURE__ */ new Map(); + const taskFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".md")).map((e) => e.name).sort(); + for (const name of taskFiles) { + const entry = { name }; + const file = path5.join(tasksDir, entry.name); + const content = fs5.readFileSync(file, "utf8"); + const id = extractPlanId(content, file); + if (id === null) { + errors.push(`task file ${entry.name} has no integer id in its frontmatter.`); + continue; + } + const duplicate = seen.get(id); + if (duplicate !== void 0) { + errors.push(`task id ${id} appears in both ${duplicate} and ${entry.name}.`); + continue; + } + seen.set(id, entry.name); + tasks.push({ id, file, content }); + } + if (tasks.length === 0) errors.push("plan has no task files to route."); + if (errors.length > 0) return { kind: "invalid", errors }; + return { kind: "tasks", tasks }; +}; +var main = () => { + const [mode, planIdArg, ...rest] = process.argv.slice(2); + if (mode !== "profiles" && mode !== "apply" || !planIdArg) usage(); + const resolved = resolvePlan(planIdArg); + if (!resolved) { + emit({ kind: "infrastructure-failure", detail: `plan "${planIdArg}" did not resolve.` }, 2); + return; + } + const configResult = loadRoutingConfig(resolved.strikethrooRoot, SUPPORTED_HARNESSES); + if (configResult.kind === "invalid") { + emit({ kind: "invalid-config", errors: configResult.errors }, 1); + } + if (configResult.kind !== "config") { + emit({ kind: configResult.kind }, 0); + return; + } + const config = configResult.config; + if (mode === "profiles") { + emit( + { + kind: "profiles", + profiles: config.profiles.map((profile) => ({ + name: profile.name, + description: profile.description, + targetCount: profile.targets.length + })), + customResolver: config.resolverScript !== void 0 + }, + 0 + ); + } + const [assignmentFile, ...extraArgs] = rest; + if (!assignmentFile || extraArgs.length > 0) usage(); + const documents = readTaskDocuments(resolved.planDir); + if (documents.kind === "invalid") { + emit({ kind: "invalid-tasks", errors: documents.errors }, 1); + return; + } + let rawMap; + try { + rawMap = JSON.parse(fs5.readFileSync(assignmentFile, "utf8")); + } catch (error) { + emit( + { + kind: "invalid-assignments", + errors: [ + `could not read assignment map: ${error instanceof Error ? error.message : String(error)}` + ] + }, + 1 + ); + return; + } + const assignmentResult = validateAssignments( + rawMap, + documents.tasks.map((task) => task.id), + config.profiles.map((profile) => profile.name) + ); + if (assignmentResult.kind === "invalid") { + emit({ kind: "invalid-assignments", errors: assignmentResult.errors }, 1); + return; + } + const staged = []; + for (const task of documents.tasks) { + const profile = assignmentResult.assignments.get(task.id); + if (!profile) { + emit({ kind: "routing-failure", detail: `no profile assigned for task ${task.id}.` }, 1); + return; + } + let next; + try { + next = writeExecutionProfileFrontmatter(task.content, profile); + } catch (error) { + emit( + { + kind: "routing-failure", + detail: `task ${task.id} (${path5.basename(task.file)}): ${error instanceof Error ? error.message : String(error)}` + }, + 1 + ); + return; + } + if (!next.includes(`execution_profile: ${JSON.stringify(profile)}`)) { + emit( + { kind: "routing-failure", detail: `task ${task.id} would not verify after routing.` }, + 1 + ); + return; + } + staged.push({ task, next, profile }); + } + const written = []; + try { + for (const { task, next } of staged) { + fs5.writeFileSync(task.file, next); + written.push(task); + } + for (const { task, next } of staged) { + const reread = fs5.readFileSync(task.file, "utf8"); + if (reread !== next) { + throw new Error(`task ${task.id} failed post-write verification.`); + } + } + } catch (error) { + for (const task of written) { + try { + fs5.writeFileSync(task.file, task.content); + } catch { + } + } + emit( + { + kind: "infrastructure-failure", + detail: `routing aborted and rolled back: ${error instanceof Error ? error.message : String(error)}` + }, + 2 + ); + return; + } + emit( + { + kind: "routed", + tasks: staged.map(({ task, profile }) => ({ + id: task.id, + file: task.file, + executionProfile: profile + })) + }, + 0 + ); +}; +try { + main(); +} catch (error) { + emit( + { + kind: "infrastructure-failure", + detail: `execution routing failed: ${error instanceof Error ? error.message : String(error)}` + }, + 2 + ); +} +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.agents/skills/st-refine-plan/SKILL.md b/.agents/skills/st-refine-plan/SKILL.md new file mode 100644 index 0000000..065b213 --- /dev/null +++ b/.agents/skills/st-refine-plan/SKILL.md @@ -0,0 +1,132 @@ +--- +name: st-refine-plan +description: Use when the user asks to review, refine, improve, interrogate, pressure-test, or update an existing Strikethroo plan by plan ID in this repository — triggers include refine plan, improve plan, review plan, red-team the plan, update plan. Do not use to create a new plan, to generate tasks, or for generic brainstorming outside Strikethroo. +--- + +# st-refine-plan + +## Inputs + +The user supplies the numeric plan ID conversationally, plus any optional refinement notes. + +## Operating Procedure + +### 1. Locate the strikethroo root + +Run `scripts/find-strikethroo-root.cjs` from the user's working directory. If +it exits non-zero, stop and ask the user to run `npx strikethroo init`. + +Treat the path it prints as `` for every subsequent step. + +Delegated execution workers skip this step and do not emit update notices. + +Run `scripts/check-for-updates.cjs ""` as a separate command using this +skill's script path. Keep the user's working directory. Read the one JSON line +on stdout. When `notice` is present, retain its exact text for the final +user-facing response. Never pause for permission and never run an update. + +### 2. Resolve the plan + +Run `scripts/validate-plan-blueprint.cjs planFile` for the plan +file's absolute path. Another field name prints that field instead. + +If the script exits non-zero, stop and ask the user to confirm the plan ID. +Do not guess a different ID. + +### 3. Load project context + +Read `/config/STRIKETHROO.md` for this project's directory conventions. +Read `/config/hooks/PRE_PLAN.md` and execute its instructions before +proceeding. Read `/config/templates/PLAN_TEMPLATE.md`; the refined plan +must still conform to it. Read `/config/shared/clarification-gate.md` +and apply it in the Clarification Loop. + +### 4. Baseline Review + +Read the entire plan end-to-end without modifying it. Record every +contradiction and every gap you find under these lenses: + +- **Context gaps**: missing background, assumptions, competing priorities. +- **Technical gaps**: underspecified architecture, unclear interfaces, missing diagrams. +- **Risk gaps**: untracked risks, missing mitigations, hand-wavy success metrics. +- **Scope issues**: gold-plating, ambiguous boundaries, requirements that + contradict YAGNI. + +Document each one as `{section, issue, severity, proposed fix}`. + +### 5. Clarification Loop + +**Default to Interactive Clarification.** Switch to **Autonomous +Clarification** only when one of these holds without interpretation: + +- The user's request names the mode by intent, with a keyword such as "auto", + "autonomous", "non-interactive", "without asking me", or "don't ask". +- An upstream orchestrator (for example the `st-full-workflow` skill) declared + autonomous operation for this invocation in the prompt passed to this skill. + +Otherwise use Interactive Clarification, even when the user's presence is +uncertain. Do not infer autonomous mode from indirect signals such as terse +prompts, scripted-looking input, or absence of recent user messages. + +Either branch starts from the gaps documented in the Baseline Review. Think +harder before raising one: only put forward an uncertainty you can cite. +Append every resolution to the plan document's "Plan Clarifications" table in +its existing question/answer format, marking each entry's source. + +#### Interactive Clarification + +Follow the clarification cadence in `/config/shared/clarification-gate.md`. + +1. Ask one question at a time per that cadence; never dump them as a batch. +2. Prefill each question with the most plausible answer, and always offer an + "Other / open-ended" option for the nuances you did not anticipate. +3. **STOP AND ASK**: Put each question to the user and halt execution to await + their input. Do not simulate the user's response. Do not proceed to step 6 + until you have received explicit answers and confirmed the resolved scope. +4. Record a question the user cannot or will not answer as unresolved, with + mitigation notes so downstream assistants know the risk, then proceed with + the available context. +5. Re-evaluate whether the answers opened new gaps. If so, repeat this loop. + +#### Autonomous Clarification + +1. Resolve each gap from the codebase, its configuration files, its + documentation, and the project's established patterns. Fall back to a + reasonable assumption only where those do not answer it. +2. Mark each resolution's source as "auto-resolved" (confirmed in the + codebase) or "assumption" (best-effort guess, with its rationale). +3. Record a gap you can resolve neither way as unresolved, with mitigation + notes so downstream assistants know the risk. + +### 6. Refinement Implementation + +Refine the plan in place, at the path step 2 resolved. + +1. **Maintain Identity**: Keep the existing `id` and directory. Never allocate + a new plan ID and never move the plan. +2. **Structure Compliance**: Keep the plan conformant to + `/config/templates/PLAN_TEMPLATE.md`, adding any missing section. +3. **Content Updates**: + - Refresh the executive summary against the clarifications. + - Update the architectural sections, diagrams, and risk mitigations the + gaps named. + - Trim scope creep that is not explicitly required. + - Point each affected section back at the Q&A table. +4. **Net-New Sections**: Add a subsection the plan now needs (Decision Log, + Data Contracts) under `Notes`, clearly labeled. +5. **Change Log**: Append to `Notes` a bullet stating what this session + changed, such as + `- 2025-03-16: Clarified auth flow tokens and updated architecture diagram`. + +### 7. Run the post-plan hook + +Execute `/config/hooks/POST_PLAN.md`. + +When the retained update `notice` is present, append that exact sentence after +the structured summary block, or after your final response when this skill emits +no summary block. Nothing may follow the notice. + +## Failure Modes + +- **A helper script fails unexpectedly.** Surface stderr to the user and + stop — do not fall back to manual path discovery. diff --git a/.agents/skills/st-refine-plan/scripts/check-for-updates.cjs b/.agents/skills/st-refine-plan/scripts/check-for-updates.cjs new file mode 100644 index 0000000..72f9166 --- /dev/null +++ b/.agents/skills/st-refine-plan/scripts/check-for-updates.cjs @@ -0,0 +1,2634 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + try { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + } catch (e) { + throw mod = 0, e; + } +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// node_modules/semver/internal/constants.js +var require_constants = __commonJS({ + "node_modules/semver/internal/constants.js"(exports2, module2) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module2.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/semver/internal/debug.js"(exports2, module2) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { + }; + module2.exports = debug; + } +}); + +// node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/semver/internal/re.js"(exports2, module2) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants(); + var debug = require_debug(); + exports2 = module2.exports = {}; + var re = exports2.re = []; + var safeRe = exports2.safeRe = []; + var src = exports2.src = []; + var safeSrc = exports2.safeSrc = []; + var t = exports2.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value; + }; + var createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + safeSrc[index] = safe; + re[index] = new RegExp(value, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports2.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports2.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports2.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/semver/internal/parse-options.js"(exports2, module2) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module2.exports = parseOptions; + } +}); + +// node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/semver/internal/identifiers.js"(exports2, module2) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module2.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/semver/classes/semver.js"(exports2, module2) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var isPrereleaseIdentifier = (prerelease2, identifier) => { + const identifiers = identifier.split("."); + if (identifiers.length > prerelease2.length) { + return false; + } + for (let i = 0; i < identifiers.length; i++) { + if (compareIdentifiers(prerelease2[i], identifiers[i]) !== 0) { + return false; + } + } + return true; + }; + var SemVer = class _SemVer { + constructor(version, options) { + options = parseOptions(options); + if (version instanceof _SemVer) { + if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) { + return version; + } else { + version = version.version; + } + } else if (typeof version !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`); + } + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version}`); + } + this.raw = version; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match || match[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease2 = [identifier, base]; + if (identifierBase === false) { + prerelease2 = [identifier]; + } + if (isPrereleaseIdentifier(this.prerelease, identifier)) { + const prereleaseBase = this.prerelease[identifier.split(".").length]; + if (isNaN(prereleaseBase)) { + this.prerelease = prerelease2; + } + } else { + this.prerelease = prerelease2; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module2.exports = SemVer; + } +}); + +// node_modules/semver/functions/parse.js +var require_parse = __commonJS({ + "node_modules/semver/functions/parse.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = (version, options, throwErrors = false) => { + if (version instanceof SemVer) { + return version; + } + try { + return new SemVer(version, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module2.exports = parse; + } +}); + +// node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/semver/functions/valid.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var valid2 = (version, options) => { + const v = parse(version, options); + return v ? v.version : null; + }; + module2.exports = valid2; + } +}); + +// node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/semver/functions/clean.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module2.exports = clean; + } +}); + +// node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/semver/functions/inc.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var inc = (version, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version instanceof SemVer ? version.version : version, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module2.exports = inc; + } +}); + +// node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/semver/functions/diff.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var diff = (version1, version2) => { + const v1 = parse(version1, null, true); + const v2 = parse(version2, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module2.exports = diff; + } +}); + +// node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/semver/functions/major.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module2.exports = major; + } +}); + +// node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/semver/functions/minor.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module2.exports = minor; + } +}); + +// node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/semver/functions/patch.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module2.exports = patch; + } +}); + +// node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/semver/functions/prerelease.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var prerelease2 = (version, options) => { + const parsed = parse(version, options); + return parsed && parsed.prerelease.length ? parsed.prerelease : null; + }; + module2.exports = prerelease2; + } +}); + +// node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/semver/functions/compare.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module2.exports = compare; + } +}); + +// node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/semver/functions/rcompare.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module2.exports = rcompare; + } +}); + +// node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/semver/functions/compare-loose.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module2.exports = compareLoose; + } +}); + +// node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/semver/functions/compare-build.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module2.exports = compareBuild; + } +}); + +// node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/semver/functions/sort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module2.exports = sort; + } +}); + +// node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/semver/functions/rsort.js"(exports2, module2) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module2.exports = rsort; + } +}); + +// node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/semver/functions/gt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gt2 = (a, b, loose) => compare(a, b, loose) > 0; + module2.exports = gt2; + } +}); + +// node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/semver/functions/lt.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lt2 = (a, b, loose) => compare(a, b, loose) < 0; + module2.exports = lt2; + } +}); + +// node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/semver/functions/eq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var eq = (a, b, loose) => compare(a, b, loose) === 0; + module2.exports = eq; + } +}); + +// node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/semver/functions/neq.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module2.exports = neq; + } +}); + +// node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/semver/functions/gte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module2.exports = gte; + } +}); + +// node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/semver/functions/lte.js"(exports2, module2) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module2.exports = lte; + } +}); + +// node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/semver/functions/cmp.js"(exports2, module2) { + "use strict"; + var eq = require_eq(); + var neq = require_neq(); + var gt2 = require_gt(); + var gte = require_gte(); + var lt2 = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt2(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt2(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module2.exports = cmp; + } +}); + +// node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/semver/functions/coerce.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var parse = require_parse(); + var { safeRe: re, t } = require_re(); + var coerce = (version, options) => { + if (version instanceof SemVer) { + return version; + } + if (typeof version === "number") { + version = String(version); + } + if (typeof version !== "string") { + return null; + } + options = options || {}; + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) { + if (!match || next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match === null) { + return null; + } + const major = match[2]; + const minor = match[3] || "0"; + const patch = match[4] || "0"; + const prerelease2 = options.includePrerelease && match[5] ? `-${match[5]}` : ""; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ""; + return parse(`${major}.${minor}.${patch}${prerelease2}${build}`, options); + }; + module2.exports = coerce; + } +}); + +// node_modules/semver/functions/truncate.js +var require_truncate = __commonJS({ + "node_modules/semver/functions/truncate.js"(exports2, module2) { + "use strict"; + var parse = require_parse(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var truncate = (version, truncation, options) => { + if (!constants2.RELEASE_TYPES.includes(truncation)) { + return null; + } + const clonedVersion = cloneInputVersion(version, options); + return clonedVersion && doTruncation(clonedVersion, truncation); + }; + var cloneInputVersion = (version, options) => { + const versionStringToParse = version instanceof SemVer ? version.version : version; + return parse(versionStringToParse, options); + }; + var doTruncation = (version, truncation) => { + if (isPrerelease(truncation)) { + return version.version; + } + version.prerelease = []; + switch (truncation) { + case "major": + version.minor = 0; + version.patch = 0; + break; + case "minor": + version.patch = 0; + break; + } + return version.format(); + }; + var isPrerelease = (type) => { + return type.startsWith("pre"); + }; + module2.exports = truncate; + } +}); + +// node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/semver/internal/lrucache.js"(exports2, module2) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value = this.map.get(key); + if (value === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value); + return value; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value) { + const deleted = this.delete(key); + if (!deleted && value !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value); + } + return this; + } + }; + module2.exports = LRUCache; + } +}); + +// node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/semver/classes/range.js"(exports2, module2) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range, options) { + options = parseOptions(options); + if (range instanceof _Range) { + if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { + return range; + } else { + return new _Range(range.raw, options); + } + } + if (range instanceof Comparator) { + this.raw = range.value; + this.set = [[range]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range) { + range = range.replace(BUILDSTRIPRE, ""); + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range; + const cached = cache.get(memoKey); + if (cached) { + return cached; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range); + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range); + range = range.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range); + range = range.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range); + let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range, options) { + if (!(range instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version) { + if (!version) { + return false; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true; + } + } + return false; + } + }; + module2.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + src, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants(); + var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g"); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p); + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + if (invalidXRangeOrder(M, m, p)) { + return comp; + } + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false; + } + } + if (version.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === Comparator.ANY) { + continue; + } + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/semver/classes/comparator.js"(exports2, module2) { + "use strict"; + var ANY = /* @__PURE__ */ Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version) { + debug("Comparator.test", version, this.options.loose); + if (this.semver === ANY || version === ANY) { + return true; + } + if (typeof version === "string") { + try { + version = new SemVer(version, this.options); + } catch (er) { + return false; + } + } + return cmp(version, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module2.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/semver/functions/satisfies.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var satisfies = (version, range, options) => { + try { + range = new Range(range, options); + } catch (er) { + return false; + } + return range.test(version); + }; + module2.exports = satisfies; + } +}); + +// node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/semver/ranges/to-comparators.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var toComparators = (range, options) => new Range(range, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module2.exports = toComparators; + } +}); + +// node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module2.exports = maxSatisfying; + } +}); + +// node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module2.exports = minSatisfying; + } +}); + +// node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/semver/ranges/min-version.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt2 = require_gt(); + var minVersion = (range, loose) => { + range = new Range(range, loose); + let minver = new SemVer("0.0.0"); + if (range.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt2(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt2(minver, setMin))) { + minver = setMin; + } + } + if (minver && range.test(minver)) { + return minver; + } + return null; + }; + module2.exports = minVersion; + } +}); + +// node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/semver/ranges/valid.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var validRange = (range, options) => { + try { + return new Range(range, options).range || "*"; + } catch (er) { + return null; + } + }; + module2.exports = validRange; + } +}); + +// node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/semver/ranges/outside.js"(exports2, module2) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version, range, hilo, options) => { + version = new SemVer(version, options); + range = new Range(range, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt2; + ltefn = lte; + ltfn = lt2; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt2; + ltefn = gte; + ltfn = gt2; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version, range, options)) { + return false; + } + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; + }; + module2.exports = outside; + } +}); + +// node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/semver/ranges/gtr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var gtr = (version, range, options) => outside(version, range, ">", options); + module2.exports = gtr; + } +}); + +// node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/semver/ranges/ltr.js"(exports2, module2) { + "use strict"; + var outside = require_outside(); + var ltr = (version, range, options) => outside(version, range, "<", options); + module2.exports = ltr; + } +}); + +// node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/semver/ranges/intersects.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module2.exports = intersects; + } +}); + +// node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/semver/ranges/simplify.js"(exports2, module2) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module2.exports = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version of v) { + const included = satisfies(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range.raw === "string" ? range.raw : String(range); + return simplified.length < original.length ? simplified : range; + }; + } +}); + +// node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/semver/ranges/subset.js"(exports2, module2) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt2, lt2; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt2 = higherGT(gt2, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt2 = lowerLT(lt2, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt2 && lt2) { + gtltComp = compare(gt2.semver, lt2.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt2.operator !== ">=" || lt2.operator !== "<=")) { + return null; + } + } + for (const eq of eqSet) { + if (gt2 && !satisfies(eq, String(gt2), options)) { + return null; + } + if (lt2 && !satisfies(eq, String(lt2), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower; + let hasDomLT, hasDomGT; + let needDomLTPre = lt2 && !options.includePrerelease && lt2.semver.prerelease.length ? lt2.semver : false; + let needDomGTPre = gt2 && !options.includePrerelease && gt2.semver.prerelease.length ? gt2.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt2.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt2) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt2, c, options); + if (higher === c && higher !== gt2) { + return false; + } + } else if (gt2.operator === ">=" && !c.test(gt2.semver)) { + return false; + } + } + if (lt2) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower = lowerLT(lt2, c, options); + if (lower === c && lower !== lt2) { + return false; + } + } else if (lt2.operator === "<=" && !c.test(lt2.semver)) { + return false; + } + } + if (!c.operator && (lt2 || gt2) && gtltComp !== 0) { + return false; + } + } + if (gt2 && hasDomLT && !lt2 && gtltComp !== 0) { + return false; + } + if (lt2 && hasDomGT && !gt2 && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module2.exports = subset; + } +}); + +// node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/semver/index.js"(exports2, module2) { + "use strict"; + var internalRe = require_re(); + var constants2 = require_constants(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse = require_parse(); + var valid2 = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease2 = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt2 = require_gt(); + var lt2 = require_lt(); + var eq = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var truncate = require_truncate(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module2.exports = { + parse, + valid: valid2, + clean, + inc, + diff, + major, + minor, + patch, + prerelease: prerelease2, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt: gt2, + lt: lt2, + eq, + neq, + gte, + lte, + cmp, + coerce, + truncate, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants2.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants2.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + +// src/skill-scripts/check-for-updates.ts +var check_for_updates_exports = {}; +__export(check_for_updates_exports, { + main: () => main +}); +module.exports = __toCommonJS(check_for_updates_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/update-check.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var import_child_process = require("child_process"); +var semver = __toESM(require_semver2()); + +// src/types.ts +var SUPPORTED_HARNESSES = [ + "claude", + "codex", + "cursor", + "gemini", + "copilot", + "opencode" +]; + +// src/resolve-init-harnesses.ts +function normalizeSavedHarnesses(saved) { + if (!Array.isArray(saved) || saved.length === 0) { + return void 0; + } + const harnesses = saved.map((entry) => String(entry).trim().toLowerCase()); + const invalid = harnesses.filter((h) => !SUPPORTED_HARNESSES.includes(h)); + if (invalid.length > 0 || harnesses.length === 0) { + return void 0; + } + return Array.from(new Set(harnesses)); +} + +// src/skill-scripts/shared/safe-fs.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); +var import_crypto = require("crypto"); +var DEFAULT_MAX_READ_BYTES = 8 * 1024 * 1024; +var fail = (error, message) => ({ error, message }); +var errno = (err) => typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0; +var canonicalRootOf = (root) => { + try { + return fs2.realpathSync.native(path2.resolve(root)); + } catch { + return fail("not-found", "Workspace root does not exist."); + } +}; +var resolveContained = (root, input, options = {}) => { + if (typeof input !== "string" || input.includes("\0")) { + return fail("invalid-path", "Path is not valid."); + } + const givenRoot = path2.resolve(root); + const canonicalRoot = canonicalRootOf(givenRoot); + if (typeof canonicalRoot !== "string") return canonicalRoot; + const rel = path2.isAbsolute(input) ? path2.relative(givenRoot, input) : input; + const target = path2.resolve(canonicalRoot, rel); + const relative2 = path2.relative(canonicalRoot, target); + if (path2.isAbsolute(relative2) || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || relative2.includes("\0")) { + return fail("outside-root", "Path is outside the workspace root."); + } + const kind = options.expect ?? "file"; + const parts = relative2 === "" ? [] : relative2.split(path2.sep); + let current = canonicalRoot; + let stats; + try { + stats = fs2.lstatSync(canonicalRoot); + } catch { + return fail("fs-error", "Could not inspect path."); + } + for (let i = 0; i < parts.length; i += 1) { + const isLeaf = i === parts.length - 1; + current = path2.join(current, parts[i]); + try { + stats = fs2.lstatSync(current); + } catch (err) { + const code = errno(err); + if (code === "ENOENT" || code === "ENOTDIR") { + if (isLeaf && options.allowMissingLeaf) { + return { path: current, relative: relative2, exists: false }; + } + return fail("not-found", "Path does not exist."); + } + return fail("fs-error", "Could not inspect path."); + } + if (stats.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!isLeaf && !stats.isDirectory()) { + return fail("not-a-directory", "A path component is not a directory."); + } + } + if (kind === "directory" && !stats.isDirectory()) { + return fail("not-a-directory", "Path is not a directory."); + } + if (kind === "file" && !stats.isFile()) { + return fail("not-a-file", "Path is not a regular file."); + } + return { path: current, relative: relative2, exists: true, stats }; +}; +var planAtomicWrite = (root, input, options) => { + const mustExist = options.mustExist === true; + const resolved = resolveContained(root, input, { allowMissingLeaf: !mustExist }); + if ("error" in resolved) return resolved; + if (mustExist && !resolved.exists) return fail("not-found", "Path does not exist."); + const target = resolved.path; + const mode = options.mode ?? (resolved.exists && resolved.stats ? resolved.stats.mode & 511 : 384); + const temp = path2.join( + path2.dirname(target), + `.${path2.basename(target)}.${(0, import_crypto.randomBytes)(8).toString("hex")}.tmp` + ); + return { target, temp, mode, mustExist }; +}; +var recheckTarget = (target, mustExist) => { + try { + const again = fs2.lstatSync(target); + if (again.isSymbolicLink()) { + return fail("symlink", "Symbolic links inside the workspace are not allowed."); + } + if (!again.isFile()) return fail("not-a-file", "Path is not a regular file."); + } catch (err) { + if (errno(err) !== "ENOENT") return fail("fs-error", "Could not inspect path."); + if (mustExist) return fail("not-found", "Path does not exist."); + } + return void 0; +}; +var writeFileAtomicSync = (root, input, content, options = {}) => { + const plan = planAtomicWrite(root, input, options); + if ("error" in plan) return plan; + const { target, temp, mode, mustExist } = plan; + let fd; + let renamed = false; + try { + fd = fs2.openSync(temp, "wx", 384); + fs2.writeFileSync(fd, content); + fs2.fsyncSync(fd); + if (mode !== 384) fs2.fchmodSync(fd, mode); + fs2.closeSync(fd); + fd = void 0; + const refused = recheckTarget(target, mustExist); + if (refused) return refused; + fs2.renameSync(temp, target); + renamed = true; + return { path: target }; + } catch { + return fail("fs-error", "Could not write file."); + } finally { + if (fd !== void 0) { + try { + fs2.closeSync(fd); + } catch { + } + } + if (!renamed) { + try { + fs2.unlinkSync(temp); + } catch { + } + } + } +}; + +// src/skill-scripts/shared/update-check.ts +var DEFAULT_SKILL_VERSION = true ? "4.1.1" : (() => { + try { + return null.version; + } catch { + return "0.0.0"; + } +})(); +var GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/e0ipso/strikethroo/releases/latest"; +var UPDATE_COMMAND = "npx strikethroo@latest update"; +var BUNDLED_UPDATE_NOTICE_TEMPLATE = "A newer Strikethroo release is available. Run `{{updateCommand}}` to update."; +var BUNDLED_HARNESS_UPDATE_NOTICE = "A newer Strikethroo release is available. Ask the user which harnesses to use, then run `{{updateCommand}}` with `--harnesses `."; +var UPDATE_NOTICE_TEMPLATE_RELATIVE = path3.join( + "config", + "templates", + "UPDATE_NOTICE_TEMPLATE.md" +); +var REQUEST_TIMEOUT_MS = 2e3; +var MAX_RESPONSE_BYTES = 65536; +var ATTEMPT_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3; +var LOCK_STALE_MS = 3e4; +var STATE_RELATIVE_PATH = path3.join("runtime", "update-check.json"); +var LOCK_RELATIVE_PATH = path3.join("runtime", "update-check.lock"); +var defaultFetchLatestRelease = async () => { + try { + const response = await fetch(GITHUB_LATEST_RELEASE_URL, { + signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.github+json", + "User-Agent": "strikethroo-update-check" + } + }); + if (!response.ok) return null; + const reader = response.body?.getReader(); + if (!reader) return null; + const chunks = []; + let total = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + total += value.byteLength; + if (total > MAX_RESPONSE_BYTES) { + await reader.cancel(); + return null; + } + chunks.push(value); + } + const text = Buffer.concat(chunks).toString("utf8"); + const payload = JSON.parse(text); + if (payload.prerelease || payload.draft) return null; + return stableRelease(payload.tag_name); + } catch { + return null; + } +}; +var defaultFindProjectRoot = (strikethrooRoot) => { + try { + const output = (0, import_child_process.execFileSync)("git", ["-C", strikethrooRoot, "rev-parse", "--show-toplevel"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"] + }).trim(); + return output || null; + } catch { + return null; + } +}; +var defaultIsStatePathGitignored = (projectRoot, statePath) => { + try { + (0, import_child_process.execFileSync)("git", ["check-ignore", "-q", "--", statePath], { + cwd: projectRoot, + stdio: "ignore" + }); + return true; + } catch { + return false; + } +}; +var readJsonFile = (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8")); + return parsed && typeof parsed === "object" ? parsed : null; + } catch { + return null; + } +}; +var isValidState = (state) => state && typeof state === "object" ? state : {}; +var parseLock = (raw) => { + try { + const parsed = JSON.parse(raw); + if (typeof parsed.pid !== "number" || typeof parsed.claimedAt !== "string") return null; + return parsed; + } catch { + return null; + } +}; +var isLockStale = (lock, nowMs) => { + const claimedAt = Date.parse(lock.claimedAt); + if (Number.isNaN(claimedAt)) return true; + return nowMs - claimedAt >= LOCK_STALE_MS; +}; +var defaultTryAcquireLock = (lockPath, now) => { + try { + fs3.mkdirSync(path3.dirname(lockPath), { recursive: true }); + const fd = fs3.openSync(lockPath, "wx"); + try { + const payload = { pid: process.pid, claimedAt: new Date(now()).toISOString() }; + fs3.writeFileSync(fd, JSON.stringify(payload)); + } finally { + fs3.closeSync(fd); + } + return true; + } catch (err) { + const code = err.code; + if (code !== "EEXIST") return false; + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + const stale = lock ? isLockStale(lock, now()) : now() - fs3.statSync(lockPath).mtimeMs >= LOCK_STALE_MS; + if (!stale) return false; + if (lock && Number.isInteger(lock.pid) && lock.pid > 0) { + try { + process.kill(lock.pid, 0); + return false; + } catch (error) { + if (error.code !== "ESRCH") return false; + } + } + fs3.unlinkSync(lockPath); + } catch { + return false; + } + return defaultTryAcquireLock(lockPath, now); + } +}; +var defaultReleaseLock = (lockPath) => { + try { + const lock = parseLock(fs3.readFileSync(lockPath, "utf8")); + if (lock?.pid === process.pid) fs3.unlinkSync(lockPath); + } catch { + } +}; +var defaultWriteTextFile = (filePath, contents) => { + try { + const dir = path3.dirname(filePath); + fs3.mkdirSync(dir, { recursive: true }); + return !("error" in writeFileAtomicSync(dir, path3.basename(filePath), contents)); + } catch { + return false; + } +}; +var compareToRelease = (localVersion, release) => { + if (!localVersion || !release) return "unknown"; + const local = semver.valid(localVersion); + const remote = semver.valid(release); + if (!local || !remote) return "unknown"; + if (semver.lt(local, remote)) return "outdated"; + if (semver.gt(local, remote)) return "ahead"; + return "current"; +}; +var stableRelease = (value) => { + if (typeof value !== "string") return null; + const version = semver.valid(value.replace(/^v/i, "")); + return version && semver.prerelease(version) === null ? version : null; +}; +var isNoticeIntervalElapsed = (lastNoticeIssuedAt, nowMs) => { + if (typeof lastNoticeIssuedAt !== "string") return true; + const last = Date.parse(lastNoticeIssuedAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= NOTICE_INTERVAL_MS; +}; +var isAttemptIntervalElapsed = (lastAttemptAt, nowMs) => { + if (typeof lastAttemptAt !== "string") return true; + const last = Date.parse(lastAttemptAt); + if (Number.isNaN(last)) return true; + return nowMs - last >= ATTEMPT_INTERVAL_MS; +}; +var interpolateNoticeTemplate = (template, result) => template.replace( + /\{\{(updateCommand|latestRelease|workspaceVersion|skillVersion)\}\}/g, + (_, key) => result[key] ?? "unknown" +); +var readNoticeTemplate = (strikethrooRoot, readTextFile) => { + const workspaceTemplate = readTextFile( + path3.join(strikethrooRoot, UPDATE_NOTICE_TEMPLATE_RELATIVE) + ); + return workspaceTemplate?.trim() || BUNDLED_UPDATE_NOTICE_TEMPLATE; +}; +var buildNotice = (strikethrooRoot, result, readTextFile) => { + if (!result.noticeEligible) return void 0; + if (result.needsHarnessPrompt) { + return interpolateNoticeTemplate(BUNDLED_HARNESS_UPDATE_NOTICE, result); + } + return interpolateNoticeTemplate(readNoticeTemplate(strikethrooRoot, readTextFile), result); +}; +var emptyResult = (skillVersion) => ({ + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: UPDATE_COMMAND, + latestRelease: null, + workspaceVersion: null, + skillVersion, + workspaceDisposition: "unknown", + skillDisposition: "unknown" +}); +var readWorkspaceMetadata = (strikethrooRoot, readTextFile) => { + const raw = readTextFile(path3.join(strikethrooRoot, ".init-metadata.json")); + if (!raw) return { version: null, needsHarnessPrompt: true }; + try { + const metadata = JSON.parse(raw); + const version = typeof metadata.version === "string" ? semver.valid(metadata.version) : null; + const needsHarnessPrompt = !normalizeSavedHarnesses(metadata.harnesses); + return { version, needsHarnessPrompt }; + } catch { + return { version: null, needsHarnessPrompt: true }; + } +}; +var createDefaultDependencies = () => { + const now = () => Date.now(); + return { + now, + skillVersion: DEFAULT_SKILL_VERSION, + fetchLatestRelease: defaultFetchLatestRelease, + isStatePathGitignored: defaultIsStatePathGitignored, + findProjectRoot: defaultFindProjectRoot, + readTextFile: (filePath) => { + try { + if (!fs3.existsSync(filePath)) return null; + return fs3.readFileSync(filePath, "utf8"); + } catch { + return null; + } + }, + writeTextFile: defaultWriteTextFile, + tryAcquireLock: (lockPath) => defaultTryAcquireLock(lockPath, now), + releaseLock: defaultReleaseLock + }; +}; +var checkForUpdates = async (strikethrooRoot, partialDeps = {}) => { + const deps = { ...createDefaultDependencies(), ...partialDeps }; + const skillVersion = semver.valid(deps.skillVersion) ?? "unknown"; + const metadata = readWorkspaceMetadata(strikethrooRoot, deps.readTextFile); + const workspaceVersion = metadata.version; + const statePath = path3.join(strikethrooRoot, STATE_RELATIVE_PATH); + const projectRoot = deps.findProjectRoot(strikethrooRoot); + if (!projectRoot || !deps.isStatePathGitignored(projectRoot, statePath)) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceDisposition: compareToRelease(workspaceVersion, null), + skillDisposition: compareToRelease(skillVersion, null) + }; + } + const lockPath = path3.join(strikethrooRoot, LOCK_RELATIVE_PATH); + const nowMs = deps.now(); + const claimed = deps.tryAcquireLock(lockPath); + if (!claimed) { + return { + ...emptyResult(skillVersion), + needsHarnessPrompt: metadata.needsHarnessPrompt, + workspaceVersion + }; + } + try { + let workingState = isValidState(readJsonFile(statePath)); + let latestRelease = stableRelease(workingState.lastSuccessfulRelease); + if (isAttemptIntervalElapsed(workingState.lastAttemptAt, nowMs)) { + workingState = { + ...workingState, + lastAttemptAt: new Date(nowMs).toISOString(), + lastAttemptFailed: true + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + let fetched = null; + try { + fetched = stableRelease(await deps.fetchLatestRelease()); + } catch { + } + workingState.lastAttemptFailed = fetched === null; + if (fetched !== null) { + workingState.lastSuccessfulRelease = fetched; + workingState.lastSuccessfulReleaseAt = new Date(nowMs).toISOString(); + latestRelease = fetched; + } + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt + }; + } + } + const workspaceDisposition = compareToRelease(workspaceVersion, latestRelease); + const skillDisposition = compareToRelease(skillVersion, latestRelease); + const componentOutdated = workspaceDisposition === "outdated" || skillDisposition === "outdated"; + const noticeEligible = componentOutdated && isNoticeIntervalElapsed(workingState.lastNoticeIssuedAt, nowMs); + if (noticeEligible) { + workingState = { + ...workingState, + lastNoticeIssuedAt: new Date(nowMs).toISOString() + }; + if (!deps.writeTextFile(statePath, JSON.stringify(workingState))) { + return { + ...emptyResult(skillVersion), + workspaceVersion, + needsHarnessPrompt: metadata.needsHarnessPrompt, + latestRelease, + workspaceDisposition, + skillDisposition + }; + } + } + const base = { + noticeEligible, + needsHarnessPrompt: metadata.needsHarnessPrompt, + updateCommand: `${UPDATE_COMMAND} --destination-directory '${path3.resolve(strikethrooRoot, "../..").replace(/'/g, "'\\''")}'`, + latestRelease, + workspaceVersion, + skillVersion, + workspaceDisposition, + skillDisposition + }; + return { + ...base, + notice: buildNotice(strikethrooRoot, base, deps.readTextFile) + }; + } finally { + deps.releaseLock(lockPath); + } +}; + +// src/skill-scripts/check-for-updates.ts +var main = async () => { + const startPath = process.argv[2] || process.cwd(); + let result; + try { + const root = findStrikethrooRoot(startPath); + if (!root) { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } else { + result = await checkForUpdates(root); + } + } catch { + result = { + noticeEligible: false, + needsHarnessPrompt: false, + updateCommand: "npx strikethroo@latest update", + latestRelease: null, + workspaceVersion: null, + skillVersion: "0.0.0", + workspaceDisposition: "unknown", + skillDisposition: "unknown" + }; + } + process.stdout.write(`${JSON.stringify(result)} +`); + process.exit(0); +}; +if (require.main === module) { + void main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-refine-plan/scripts/find-strikethroo-root.cjs b/.agents/skills/st-refine-plan/scripts/find-strikethroo-root.cjs new file mode 100644 index 0000000..4aca84d --- /dev/null +++ b/.agents/skills/st-refine-plan/scripts/find-strikethroo-root.cjs @@ -0,0 +1,118 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/find-strikethroo-root.ts +var find_strikethroo_root_exports = {}; +__export(find_strikethroo_root_exports, { + main: () => main +}); +module.exports = __toCommonJS(find_strikethroo_root_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/find-strikethroo-root.ts +var main = () => { + const startPath = process.argv[2] || process.cwd(); + const root = findStrikethrooRoot(startPath); + if (!root) { + process.stderr.write( + `Could not find .ai/strikethroo root from ${startPath} or any parent directory. +` + ); + process.exit(1); + } + process.stdout.write(`${root} +`); + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); diff --git a/.agents/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs b/.agents/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs new file mode 100644 index 0000000..f07e9de --- /dev/null +++ b/.agents/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs @@ -0,0 +1,1508 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/skill-scripts/validate-plan-blueprint.ts +var validate_plan_blueprint_exports = {}; +__export(validate_plan_blueprint_exports, { + main: () => main +}); +module.exports = __toCommonJS(validate_plan_blueprint_exports); + +// src/skill-scripts/shared/root.ts +var fs = __toESM(require("fs")); +var path = __toESM(require("path")); +var EXPECTED_SCHEMA = true ? 4 : 4; +var isValidStrikethrooRoot = (strikethrooPath) => { + try { + if (!fs.existsSync(strikethrooPath)) return false; + if (!fs.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path.join(strikethrooPath, ".init-metadata.json"); + if (!fs.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8")); + return metadata && typeof metadata === "object" && "version" in metadata; + } catch (_err) { + return false; + } +}; +var getStrikethrooAt = (directory) => { + const strikethrooPath = path.join(directory, ".ai", "strikethroo"); + return isValidStrikethrooRoot(strikethrooPath) ? strikethrooPath : null; +}; +var getParentPaths = (currentPath, acc = []) => { + const absolutePath = path.resolve(currentPath); + const nextAcc = [...acc, absolutePath]; + const parentPath = path.dirname(absolutePath); + if (parentPath === absolutePath) return nextAcc; + return getParentPaths(parentPath, nextAcc); +}; +var checkWorkspaceSchema = (strikethrooRoot) => { + let metadata; + try { + metadata = JSON.parse( + fs.readFileSync(path.join(strikethrooRoot, ".init-metadata.json"), "utf8") + ); + } catch { + return; + } + const actual = typeof metadata.workspaceSchemaVersion === "number" ? metadata.workspaceSchemaVersion : 1; + if (actual === EXPECTED_SCHEMA) return; + if (actual < EXPECTED_SCHEMA) { + process.stderr.write( + `Workspace schema v${actual} is older than this skill requires (v${EXPECTED_SCHEMA}). Re-run \`npx strikethroo init\` with the latest CLI to update. +` + ); + } else { + process.stderr.write( + `This skill (built for workspace schema v${EXPECTED_SCHEMA}) is older than the workspace (v${actual}). Re-run \`npx skills add e0ipso/strikethroo\` to update skills. +` + ); + } + process.exit(1); +}; +var findStrikethrooRoot = (startPath = process.cwd()) => { + const paths = getParentPaths(startPath); + const found = paths.find((p) => getStrikethrooAt(p)); + if (!found) return null; + const root = getStrikethrooAt(found); + if (root) checkWorkspaceSchema(root); + return root; +}; + +// src/skill-scripts/shared/plan-scan.ts +var fs2 = __toESM(require("fs")); +var path2 = __toESM(require("path")); + +// src/skill-scripts/shared/frontmatter.ts +var ID_PATTERNS = [ + /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/im, + /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/im, + /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/im, + /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/im, + /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/im +]; +var validateId = (rawId) => { + const id = parseInt(rawId, 10); + if (Number.isNaN(id) || id < 0 || id > Number.MAX_SAFE_INTEGER) return null; + return id; +}; +var extractIdFromMarkdown = (content) => { + const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + if (!frontmatterMatch || !frontmatterMatch[1]) return null; + const block = frontmatterMatch[1]; + for (const pattern of ID_PATTERNS) { + const match = block.match(pattern); + if (match && match[1]) { + const id = validateId(match[1]); + if (id !== null) return id; + } + } + return null; +}; +var extractPlanId = (content, _filePath) => { + return extractIdFromMarkdown(content); +}; + +// src/skill-scripts/shared/plan-scan.ts +var PLAN_EXTENSIONS = [".md"]; +var scanPlanDir = (planDirPath, dirName, isArchive) => { + let entries; + try { + entries = fs2.readdirSync(planDirPath, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isFile() && PLAN_EXTENSIONS.some((ext) => e.name.endsWith(ext))).flatMap((e) => { + const filePath = path2.join(planDirPath, e.name); + try { + const content = fs2.readFileSync(filePath, "utf8"); + const id = extractPlanId(content, filePath); + if (id === null) return []; + return [{ id, file: filePath, dir: planDirPath, isArchive, name: dirName }]; + } catch (_err) { + return []; + } + }); +}; +var getAllPlans = (taskManagerRoot) => { + const sources = [ + { dir: path2.join(taskManagerRoot, "plans"), isArchive: false }, + { dir: path2.join(taskManagerRoot, "archive"), isArchive: true } + ]; + return sources.flatMap(({ dir, isArchive }) => { + if (!fs2.existsSync(dir)) return []; + let entries; + try { + entries = fs2.readdirSync(dir, { withFileTypes: true }); + } catch (_err) { + return []; + } + return entries.filter((e) => e.isDirectory()).flatMap((e) => scanPlanDir(path2.join(dir, e.name), e.name, isArchive)); + }); +}; + +// src/skill-scripts/shared/plan-resolve.ts +var fs3 = __toESM(require("fs")); +var path3 = __toESM(require("path")); +var _classifyPlanInput = (input, isAbsolute2 = path3.isAbsolute) => { + if (input === null || input === void 0 || input === "") return { kind: "invalid" }; + const candidate = String(input); + if (isAbsolute2(candidate)) return { kind: "path", planFile: candidate }; + const planId = parseInt(candidate, 10); + return Number.isNaN(planId) ? { kind: "invalid" } : { kind: "id", planId }; +}; +var isValidRootDir = (strikethrooPath) => { + try { + if (!fs3.existsSync(strikethrooPath)) return false; + if (!fs3.lstatSync(strikethrooPath).isDirectory()) return false; + const metadataPath = path3.join(strikethrooPath, ".init-metadata.json"); + if (!fs3.existsSync(metadataPath)) return false; + const metadata = JSON.parse(fs3.readFileSync(metadataPath, "utf8")); + return typeof metadata === "object" && metadata !== null; + } catch (_err) { + return false; + } +}; +var checkStandardRootShortcut = (filePath) => { + const planDir = path3.dirname(filePath); + const parentDir = path3.dirname(planDir); + const possibleRoot = path3.dirname(parentDir); + const parentBase = path3.basename(parentDir); + if (parentBase !== "plans" && parentBase !== "archive") return null; + if (path3.basename(possibleRoot) !== "strikethroo") return null; + const dotAiDir = path3.dirname(possibleRoot); + if (path3.basename(dotAiDir) !== ".ai") return null; + return isValidRootDir(possibleRoot) ? possibleRoot : null; +}; +var locateRootForPlanFile = (planFile) => { + const shortcut = checkStandardRootShortcut(planFile); + if (!shortcut) return findStrikethrooRoot(path3.dirname(planFile)); + checkWorkspaceSchema(shortcut); + return shortcut; +}; +var resolveByPath = (absolutePath) => { + let content; + try { + content = fs3.readFileSync(absolutePath, "utf8"); + } catch (_err) { + return null; + } + const planId = extractPlanId(content, absolutePath); + if (planId === null) return null; + const tmRoot = locateRootForPlanFile(absolutePath); + if (!tmRoot) return null; + return { + planFile: absolutePath, + planDir: path3.dirname(absolutePath), + strikethrooRoot: tmRoot, + planId + }; +}; +var resolveById = (planId, startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return null; + const match = getAllPlans(tmRoot).find((p) => p.id === planId); + if (!match) return null; + return { + planFile: match.file, + planDir: match.dir, + strikethrooRoot: tmRoot, + planId + }; +}; +var resolvePlan = (input, startPath = process.cwd()) => { + const classified = _classifyPlanInput(input); + switch (classified.kind) { + case "path": + return resolveByPath(classified.planFile); + case "id": + return resolveById(classified.planId, startPath); + case "invalid": + return null; + } +}; + +// src/skill-scripts/shared/blueprint-detection.ts +var fs4 = __toESM(require("fs")); +var hasExecutionBlueprint = (planFile) => { + try { + const content = fs4.readFileSync(planFile, "utf8"); + return /^## Execution Blueprint/m.test(content); + } catch (_err) { + return false; + } +}; + +// src/skill-scripts/shared/task-count.ts +var fs5 = __toESM(require("fs")); +var path4 = __toESM(require("path")); +var countTaskFiles = (planDir) => { + const tasksDir = path4.join(planDir, "tasks"); + if (!fs5.existsSync(tasksDir)) return 0; + try { + const stat = fs5.lstatSync(tasksDir); + if (!stat.isDirectory()) return 0; + return fs5.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).length; + } catch (_err) { + return 0; + } +}; + +// src/skill-scripts/shared/task-complexity.ts +var fs6 = __toESM(require("fs")); +var path5 = __toESM(require("path")); + +// src/skill-scripts/shared/complexity-score.ts +var validateComplexityScore = (value) => { + const trimmed = value.trim(); + if (!/^\d+$/.test(trimmed)) { + return { valid: false, reason: "non-integer" }; + } + const parsed = Number.parseInt(trimmed, 10); + if (parsed < 1 || parsed > 10) { + return { valid: false, reason: "out-of-range", value: parsed }; + } + return { valid: true, value: parsed }; +}; + +// node_modules/js-yaml/dist/js-yaml.mjs +var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED"); +function defineScalarTag(tagName, options) { + return { + tagName, + nodeKind: "scalar", + implicit: options.implicit ?? false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + implicitFirstChars: options.implicitFirstChars ?? null, + resolve: options.resolve, + identify: options.identify, + represent: options.represent ?? ((data) => String(data)), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineSequenceTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "sequence", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addItem: options.addItem, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +function defineMappingTag(tagName, options) { + const carrierIsResult = options.finalize === void 0; + return { + tagName, + nodeKind: "mapping", + implicit: false, + matchByTagPrefix: options.matchByTagPrefix ?? false, + create: options.create, + addPair: options.addPair, + has: options.has, + keys: options.keys, + get: options.get, + finalize: options.finalize ?? ((carrier) => carrier), + carrierIsResult, + identify: options.identify, + represent: options.represent ?? ((data) => data), + representTagName: options.representTagName ?? (() => tagName) + }; +} +var strTag = defineScalarTag("tag:yaml.org,2002:str", { + resolve: (source) => source, + identify: (data) => typeof data === "string" +}); +var NULL_VALUES$1 = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullCoreTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES$1.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var nullJsonTag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: ["n"], + resolve: (source, isExplicit) => { + if (source === "null" || isExplicit && source === "") return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var NULL_VALUES = [ + "", + "~", + "null", + "Null", + "NULL" +]; +var nullYaml11Tag = defineScalarTag("tag:yaml.org,2002:null", { + implicit: true, + implicitFirstChars: [ + "", + "~", + "n", + "N" + ], + resolve: (source) => { + if (NULL_VALUES.indexOf(source) !== -1) return null; + return NOT_RESOLVED; + }, + identify: (object) => object === null, + represent: () => "null" +}); +var TRUE_VALUES$2 = [ + "true", + "True", + "TRUE" +]; +var FALSE_VALUES$2 = [ + "false", + "False", + "FALSE" +]; +var boolCoreTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "t", + "T", + "f", + "F" + ], + resolve: (source) => { + if (TRUE_VALUES$2.indexOf(source) !== -1) return true; + if (FALSE_VALUES$2.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES$1 = ["true"]; +var FALSE_VALUES$1 = ["false"]; +var boolJsonTag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: ["t", "f"], + resolve: (source) => { + if (TRUE_VALUES$1.indexOf(source) !== -1) return true; + if (FALSE_VALUES$1.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var TRUE_VALUES = [ + "true", + "True", + "TRUE", + "y", + "Y", + "yes", + "Yes", + "YES", + "on", + "On", + "ON" +]; +var FALSE_VALUES = [ + "false", + "False", + "FALSE", + "n", + "N", + "no", + "No", + "NO", + "off", + "Off", + "OFF" +]; +var boolYaml11Tag = defineScalarTag("tag:yaml.org,2002:bool", { + implicit: true, + implicitFirstChars: [ + "y", + "Y", + "n", + "N", + "t", + "T", + "f", + "F", + "o", + "O" + ], + resolve: (source) => { + if (TRUE_VALUES.indexOf(source) !== -1) return true; + if (FALSE_VALUES.indexOf(source) !== -1) return false; + return NOT_RESOLVED; + }, + identify: (object) => Object.prototype.toString.call(object) === "[object Boolean]", + represent: (object) => object ? "true" : "false" +}); +var YAML_INTEGER_IMPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:0o[0-7]+|0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +var YAML_INTEGER_EXPLICIT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$2(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$2(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN$1.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$2(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intCoreTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger$2, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)$"); +var YAML_INTEGER_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1]+|[-+]?0o[0-7]+|[-+]?0x[0-9a-fA-F]+|[-+]?[0-9]+)$"); +function parseYamlInteger$1(source) { + let value = source; + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0o")) return sign * parseInt(value.slice(2), 8); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + return sign * parseInt(value, 10); +} +function resolveYamlInteger$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_INTEGER_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + } else if (!YAML_INTEGER_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger$1(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intJsonTag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlInteger$1, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_INTEGER_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?0x[0-9a-fA-F_]+|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|[-+]?(?:0|[1-9][0-9_]*))$"); +function parseYamlInteger(source) { + let value = source.replace(/_/g, ""); + let sign = 1; + if (value[0] === "-" || value[0] === "+") { + if (value[0] === "-") sign = -1; + value = value.slice(1); + } + if (value.startsWith("0b")) return sign * parseInt(value.slice(2), 2); + if (value.startsWith("0x")) return sign * parseInt(value.slice(2), 16); + if (value.includes(":")) { + let result = 0; + for (const part of value.split(":")) result = result * 60 + Number(part); + return sign * result; + } + if (value !== "0" && value[0] === "0") return sign * parseInt(value, 8); + return sign * parseInt(value, 10); +} +function resolveYamlInteger(source) { + if (!YAML_INTEGER_PATTERN.test(source)) return NOT_RESOLVED; + const result = parseYamlInteger(source); + return Number.isFinite(result) ? result : NOT_RESOLVED; +} +var intYaml11Tag = defineScalarTag("tag:yaml.org,2002:int", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ..."0123456789" + ], + resolve: resolveYamlInteger, + identify: (object) => Number.isInteger(object) && !Object.is(object, -0) && object.toString(10).indexOf("e") < 0, + represent: (object) => object.toString(10) +}); +var YAML_FLOAT_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN$1 = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$2(source) { + if (!YAML_FLOAT_PATTERN$1.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN$1.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$2(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatCoreTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat$2, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$2 +}); +var YAML_FLOAT_IMPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$"); +var YAML_FLOAT_EXPLICIT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?[0-9]+(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|[-+]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat$1(source, isExplicit) { + if (isExplicit) { + if (!YAML_FLOAT_EXPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase(); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + const result2 = sign * parseFloat(value); + return Number.isFinite(result2) ? result2 : NOT_RESOLVED; + } + if (!YAML_FLOAT_IMPLICIT_PATTERN.test(source)) return NOT_RESOLVED; + const result = Number(source); + if (Number.isFinite(result)) return result; + return NOT_RESOLVED; +} +function representYamlFloat$1(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatJsonTag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: ["-", ..."0123456789"], + resolve: resolveYamlFloat$1, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat$1 +}); +var YAML_FLOAT_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?(?:(?:[0-9][0-9_]*)?\\.[0-9_]*)(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +var YAML_FLOAT_SPECIAL_PATTERN = /* @__PURE__ */ new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); +function resolveYamlFloat(source) { + if (!YAML_FLOAT_PATTERN.test(source)) return NOT_RESOLVED; + let value = source.toLowerCase().replace(/_/g, ""); + const sign = value[0] === "-" ? -1 : 1; + if ("+-".includes(value[0])) value = value.slice(1); + if (value === ".inf") return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + if (value === ".nan") return NaN; + let result = 0; + if (value.includes(":")) { + for (const part of value.split(":")) result = result * 60 + Number(part); + result *= sign; + } else result = sign * parseFloat(value); + if (Number.isFinite(result) || YAML_FLOAT_SPECIAL_PATTERN.test(source)) return result; + return NOT_RESOLVED; +} +function representYamlFloat(object) { + if (isNaN(object)) return ".nan"; + if (object === Number.POSITIVE_INFINITY) return ".inf"; + if (object === Number.NEGATIVE_INFINITY) return "-.inf"; + if (Object.is(object, -0)) return "-0.0"; + const result = object.toString(10); + return /^[-+]?[0-9]+e/.test(result) ? result.replace("e", ".e") : result; +} +var floatYaml11Tag = defineScalarTag("tag:yaml.org,2002:float", { + implicit: true, + implicitFirstChars: [ + "-", + "+", + ".", + ..."0123456789" + ], + resolve: resolveYamlFloat, + identify: (object) => typeof object === "number" && (!Number.isInteger(object) || Object.is(object, -0) || object.toString(10).indexOf("e") >= 0), + represent: representYamlFloat +}); +var mergeTag = defineScalarTag("tag:yaml.org,2002:merge", { + implicit: true, + implicitFirstChars: ["<"], + resolve: (source, isExplicit) => { + if (source === "<<" || isExplicit && source === "") return "<<"; + return NOT_RESOLVED; + }, + identify: () => false +}); +var BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/; +function resolveYamlBinary(source) { + const input = source.replace(/\s/g, ""); + if (input.length % 4 !== 0 || !BASE64_PATTERN.test(input)) return NOT_RESOLVED; + const binary = atob(input); + const result = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index); + return result; +} +function representYamlBinary(object) { + let binary = ""; + for (let index = 0; index < object.length; index++) binary += String.fromCharCode(object[index]); + return btoa(binary); +} +var binaryTag = defineScalarTag("tag:yaml.org,2002:binary", { + resolve: resolveYamlBinary, + identify: (object) => Object.prototype.toString.call(object) === "[object Uint8Array]", + represent: representYamlBinary +}); +var YAML_DATE_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"); +var YAML_TIMESTAMP_REGEXP = /* @__PURE__ */ new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); +function makeUtcDate(year, month, day, hour = 0, minute = 0, second = 0, fraction = 0) { + const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + date.setUTCFullYear(year, month, day); + return date; +} +function resolveYamlTimestamp(source) { + let match = YAML_DATE_REGEXP.exec(source); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(source); + if (match === null) return NOT_RESOLVED; + const year = +match[1]; + const month = +match[2] - 1; + const day = +match[3]; + if (!match[4]) { + const date2 = makeUtcDate(year, month, day); + if (date2.getUTCFullYear() !== year || date2.getUTCMonth() !== month || date2.getUTCDate() !== day) return NOT_RESOLVED; + return date2; + } + const hour = +match[4]; + const minute = +match[5]; + const second = +match[6]; + let fraction = 0; + if (hour > 23 || minute > 59 || second > 59) return NOT_RESOLVED; + if (match[7]) { + let value = match[7].slice(0, 3); + while (value.length < 3) value += "0"; + fraction = +value; + } + const date = makeUtcDate(year, month, day, hour, minute, second, fraction); + if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) return NOT_RESOLVED; + if (match[9]) { + const offsetHour = +match[10]; + const offsetMinute = +(match[11] || 0); + if (offsetHour > 23 || offsetMinute > 59) return NOT_RESOLVED; + const offset = (offsetHour * 60 + offsetMinute) * 6e4; + date.setTime(date.getTime() - (match[9] === "-" ? -offset : offset)); + } + return date; +} +var timestampTag = defineScalarTag("tag:yaml.org,2002:timestamp", { + implicit: true, + implicitFirstChars: [..."0123456789"], + resolve: resolveYamlTimestamp, + identify: (object) => object instanceof Date, + represent: (object) => object.toISOString() +}); +var seqTag = defineSequenceTag("tag:yaml.org,2002:seq", { + create: () => [], + addItem: (container, item) => { + container.push(item); + }, + identify: Array.isArray +}); +function isPlainObject(data) { + if (data === null || typeof data !== "object" || Array.isArray(data)) return false; + const prototype = Object.getPrototypeOf(data); + return prototype === null || prototype === Object.prototype; +} +var omapTag = defineSequenceTag("tag:yaml.org,2002:omap", { + create: () => ({ + list: [], + seen: /* @__PURE__ */ new Set() + }), + addItem: (carrier, item) => { + let key; + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve an ordered map item"; + key = item.keys().next().value; + } else if (isPlainObject(item)) { + const itemKeys = Object.keys(item); + if (itemKeys.length !== 1) return "cannot resolve an ordered map item"; + key = itemKeys[0]; + } else return "cannot resolve an ordered map item"; + if (carrier.seen.has(key)) return "duplicate key in ordered map"; + carrier.seen.add(key); + carrier.list.push(item); + return ""; + }, + finalize: (carrier) => carrier.list, + identify: () => false +}); +var pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", { + create: () => [], + addItem: (container, item) => { + if (item instanceof Map) { + if (item.size !== 1) return "cannot resolve a pairs item"; + container.push(item.entries().next().value); + return ""; + } + if (Object.prototype.toString.call(item) !== "[object Object]") return "cannot resolve a pairs item"; + const object = item; + const keys = Object.keys(object); + if (keys.length !== 1) return "cannot resolve a pairs item"; + container.push([keys[0], object[keys[0]]]); + return ""; + }, + identify: () => false +}); +var mapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + if (key !== null && typeof key === "object") return "object-based map does not support complex keys"; + const normalizedKey = String(key); + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + if (key !== null && typeof key === "object") return false; + return Object.prototype.hasOwnProperty.call(container, String(key)); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var setTag = defineMappingTag("tag:yaml.org,2002:set", { + create: () => /* @__PURE__ */ new Set(), + identify: (data) => data instanceof Set, + represent: (data) => { + const map = /* @__PURE__ */ new Map(); + for (const key of data) map.set(key, null); + return map; + }, + addPair: (container, key, value) => { + if (value !== null) return "cannot resolve a set item"; + container.add(key); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: () => null +}); +function createTagDefinitionMap() { + return { + scalar: /* @__PURE__ */ Object.create(null), + sequence: /* @__PURE__ */ Object.create(null), + mapping: /* @__PURE__ */ Object.create(null) + }; +} +function createTagDefinitionListMap() { + return { + scalar: [], + sequence: [], + mapping: [] + }; +} +function compileTags(tags) { + const result = []; + for (const tag of tags) { + let index = result.length; + for (let previousIndex = 0; previousIndex < result.length; previousIndex++) { + const previous = result[previousIndex]; + if (previous.nodeKind === tag.nodeKind && previous.tagName === tag.tagName && previous.matchByTagPrefix === tag.matchByTagPrefix) { + index = previousIndex; + break; + } + } + result[index] = tag; + } + return result; +} +var Schema = class Schema2 { + tags; + /** @internal */ + implicitScalarTags; + /** + * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds + * the resolvers that may match that key, in schema order; a key absent from + * the map uses + * {@link Schema.implicitScalarAnyFirstChar} + * (resolvers that declared no first-char constraint, so they apply to any + * first character). + */ + implicitScalarByFirstChar; + implicitScalarAnyFirstChar; + /** + * The default scalar tag (`!!str`), resolved once so the composer's fallback + * for unresolved plain scalars avoids a keyed lookup per scalar. + * + * @internal + */ + defaultScalarTag; + /** + * The default container tags (`!!seq` / `!!map`), used by the dumper: when a + * value is identified by its default tag, the tag is implicit and not + * printed. Undefined if the schema does not define them (then such values + * can't be dumped). + * + * @internal + */ + defaultSequenceTag; + /** @internal */ + defaultMappingTag; + exact; + prefix; + constructor(tags) { + const compiledTags = compileTags(tags); + const implicitScalarTags = []; + const exact = createTagDefinitionMap(); + const prefix = createTagDefinitionListMap(); + for (const tag of compiledTags) { + if (tag.nodeKind === "scalar" && tag.implicit) { + if (tag.matchByTagPrefix) throw new Error("Implicit scalar tags cannot match by tag prefix"); + implicitScalarTags.push(tag); + } + switch (tag.nodeKind) { + case "scalar": + if (tag.matchByTagPrefix) prefix.scalar.push(tag); + else exact.scalar[tag.tagName] = tag; + break; + case "sequence": + if (tag.matchByTagPrefix) prefix.sequence.push(tag); + else exact.sequence[tag.tagName] = tag; + break; + case "mapping": + if (tag.matchByTagPrefix) prefix.mapping.push(tag); + else exact.mapping[tag.tagName] = tag; + break; + } + } + const implicitScalarAnyFirstChar = implicitScalarTags.filter((tag) => tag.implicitFirstChars === null); + const keys = /* @__PURE__ */ new Set(); + for (const tag of implicitScalarTags) if (tag.implicitFirstChars !== null) for (const key of tag.implicitFirstChars) keys.add(key); + const implicitScalarByFirstChar = /* @__PURE__ */ new Map(); + for (const key of keys) implicitScalarByFirstChar.set(key, implicitScalarTags.filter((tag) => tag.implicitFirstChars === null || tag.implicitFirstChars.indexOf(key) !== -1)); + const defaultScalarTag = exact.scalar["tag:yaml.org,2002:str"]; + if (!defaultScalarTag) throw new Error("schema does not define the default scalar tag (tag:yaml.org,2002:str)"); + this.tags = compiledTags; + this.implicitScalarTags = implicitScalarTags; + this.implicitScalarByFirstChar = implicitScalarByFirstChar; + this.implicitScalarAnyFirstChar = implicitScalarAnyFirstChar; + this.defaultScalarTag = defaultScalarTag; + this.defaultSequenceTag = exact.sequence["tag:yaml.org,2002:seq"]; + this.defaultMappingTag = exact.mapping["tag:yaml.org,2002:map"]; + this.exact = exact; + this.prefix = prefix; + } + /** @internal */ + lookupScalarTag(tagName) { + const exactTag = this.exact.scalar[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupSequenceTag(tagName) { + const exactTag = this.exact.sequence[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + lookupMappingTag(tagName) { + const exactTag = this.exact.mapping[tagName]; + if (exactTag) return exactTag; + for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag; + } + /** @internal */ + resolveImplicitScalarTag(source) { + const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar; + for (const tag2 of candidates) { + const value = tag2.resolve(source, false, tag2.tagName); + if (value !== NOT_RESOLVED) return { + value, + tag: tag2 + }; + } + const tag = this.defaultScalarTag; + return { + value: tag.resolve(source, false, tag.tagName), + tag + }; + } + /** + * Creates a new schema with the specified tags added. If a tag already + * exists, it is replaced by the specified tag. + * + * @example + * + * ```javascript + * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml' + * + * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag) + * ``` + */ + withTags(...tags) { + let flatTags = []; + for (const tag of tags) flatTags = flatTags.concat(tag); + return new Schema2([...this.tags, ...flatTags]); + } +}; +var FAILSAFE_SCHEMA = new Schema([ + strTag, + seqTag, + mapTag +]); +var JSON_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullJsonTag, + boolJsonTag, + intJsonTag, + floatJsonTag +]); +var CORE_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullCoreTag, + boolCoreTag, + intCoreTag, + floatCoreTag +]); +var YAML11_SCHEMA = new Schema([ + ...FAILSAFE_SCHEMA.tags, + nullYaml11Tag, + boolYaml11Tag, + intYaml11Tag, + floatYaml11Tag, + timestampTag, + mergeTag, + binaryTag, + omapTag, + pairsTag, + setTag +]); +var DUMP_SCHEMA = YAML11_SCHEMA.withTags({ + ...intYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = intYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result; + } +}, { + ...floatYaml11Tag, + resolve: (source, isExplicit, tagName) => { + const result = floatYaml11Tag.resolve(source, isExplicit, tagName); + return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result; + } +}); +var realMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => /* @__PURE__ */ new Map(), + addPair: (container, key, value) => { + container.set(key, value); + return ""; + }, + has: (container, key) => container.has(key), + keys: (container) => container.keys(), + get: (container, key) => container.get(key), + identify: (data) => data instanceof Map || isPlainObject(data), + represent: (data) => { + if (data instanceof Map) return data; + const map = /* @__PURE__ */ new Map(); + const obj = data; + for (const key of Object.keys(obj)) map.set(key, obj[key]); + return map; + } +}); +function normalizeKey(key) { + if (Array.isArray(key)) { + const array = Array.prototype.slice.call(key); + for (let index = 0; index < array.length; index++) { + if (Array.isArray(array[index])) return null; + if (typeof array[index] === "object" && Object.prototype.toString.call(array[index]) === "[object Object]") array[index] = "[object Object]"; + } + return String(array); + } + if (typeof key === "object" && Object.prototype.toString.call(key) === "[object Object]") return "[object Object]"; + return String(key); +} +var legacyMapTag = defineMappingTag("tag:yaml.org,2002:map", { + create: () => ({}), + identify: isPlainObject, + represent: (o) => { + const map = /* @__PURE__ */ new Map(); + for (const key of Object.keys(o)) map.set(key, o[key]); + return map; + }, + addPair: (container, key, value) => { + const normalizedKey = normalizeKey(key); + if (normalizedKey === null) return "nested arrays are not supported inside keys"; + if (normalizedKey === "__proto__") Object.defineProperty(container, normalizedKey, { + value, + enumerable: true, + configurable: true, + writable: true + }); + else container[normalizedKey] = value; + return ""; + }, + has: (container, key) => { + const normalizedKey = normalizeKey(key); + return normalizedKey !== null && Object.prototype.hasOwnProperty.call(container, normalizedKey); + }, + keys: (container) => Object.keys(container), + get: (container, key) => { + const normalizedKey = String(key); + if (!Object.prototype.hasOwnProperty.call(container, normalizedKey)) return null; + return container[normalizedKey]; + } +}); +var EVENT_ID = { + DOCUMENT: 1, + SEQUENCE: 2, + MAPPING: 3, + SCALAR: 4, + ALIAS: 5, + POP: 6 +}; +var SCALAR_STYLE = { + PLAIN: 1, + SINGLE_QUOTED: 2, + DOUBLE_QUOTED: 3, + LITERAL_BLOCK: 4, + FOLDED_BLOCK: 5 +}; +var COLLECTION_STYLE = { + BLOCK: 1, + FLOW: 2 +}; +var CHOMPING_MODE = { + CLIP: 1, + STRIP: 2, + KEEP: 3 +}; +function simpleEscapeSequence(c) { + switch (c) { + case 48: + return "\0"; + case 97: + return "\x07"; + case 98: + return "\b"; + case 116: + return " "; + case 9: + return " "; + case 110: + return "\n"; + case 118: + return "\v"; + case 102: + return "\f"; + case 114: + return "\r"; + case 101: + return "\x1B"; + case 32: + return " "; + case 34: + return '"'; + case 47: + return "/"; + case 92: + return "\\"; + case 78: + return "\x85"; + case 95: + return "\xA0"; + case 76: + return "\u2028"; + case 80: + return "\u2029"; + default: + return ""; + } +} +var simpleEscapeCheck = new Array(256); +var simpleEscapeMap = new Array(256); +for (let i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} +var DEFAULT_TAG_HANDLERS = Object.assign(/* @__PURE__ */ Object.create(null), { + "!": "!", + "!!": "tag:yaml.org,2002:" +}); +var DEFAULT_CONSTRUCTOR_OPTIONS = { + filename: "", + schema: CORE_SCHEMA, + json: false, + maxTotalMergeKeys: 1e4, + maxAliases: -1 +}; +var NS_URI_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]])`; +var NS_TAG_CHAR = String.raw`(?:%[0-9A-Fa-f]{2}|[0-9A-Za-z\-#;/?:@&=+$.~*'()_])`; +var PATTERN_TAG_URI = new RegExp(`^(?:${NS_URI_CHAR})*$`); +var PATTERN_TAG_SUFFIX = new RegExp(`^(?:${NS_TAG_CHAR})+$`); +var PATTERN_TAG_PREFIX = new RegExp(`^(?:!(?:${NS_URI_CHAR})*|${NS_TAG_CHAR}(?:${NS_URI_CHAR})*)$`); +var DEFAULT_PARSER_OPTIONS = { + filename: "", + maxDepth: 100 +}; +var DEFAULT_LOAD_OPTIONS = { + ...DEFAULT_PARSER_OPTIONS, + ...DEFAULT_CONSTRUCTOR_OPTIONS +}; +function hasBit(mask, bit) { + return (mask & 1 << bit) !== 0; +} +var DEFAULT_SCALAR_STYLE_RULES = { + applyQuoteFlowKeysOption, + doubleQuoteForInvisibles, + doubleQuoteWhitespaceOnly, + applyForceQuotesOption, + tryLongOrMultilineAsBlock, + quoteInvalidPlain, + fallbackToDoubleQuoted +}; +function _preferredQuotedStyle(layout) { + if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED; + return SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyQuoteFlowKeysOption(layout) { + if (!layout.presenterOptions.quoteFlowKeys) return; + if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return; + layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteForInvisibles(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function doubleQuoteWhitespaceOnly(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +function applyForceQuotesOption(layout) { + if (!layout.presenterOptions.forceQuotes) return; + if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return; + if (layout.node.tag !== layout.presenterOptions.schema.defaultScalarTag.tagName) return; + layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout); +} +function tryLongOrMultilineAsBlock(layout) { + if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return; + const value = layout.node.value; + const multiline = value.indexOf("\n") !== -1; + if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) { + if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; + return; + } + const w = layout.presenterOptions.lineWidth; + if (w === -1) { + if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; + return; + } + const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent); + let position = 0; + let shouldFold = false; + while (position <= value.length) { + let lineEnd = value.length; + const nextLineBreak = value.indexOf("\n", position); + if (nextLineBreak !== -1) lineEnd = nextLineBreak; + const line = value.slice(position, lineEnd); + if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true; + if (nextLineBreak === -1) break; + position = nextLineBreak + 1; + } + if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK; + else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK; +} +function quoteInvalidPlain(layout) { + if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout); +} +function fallbackToDoubleQuoted(layout) { + if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED; +} +var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]"; +var SRC_B_CHAR = "[\\n\\r]"; +var SRC_C_BYTE_ORDER_MARK = "\\uFEFF"; +var SRC_S_WHITE = "[ \\t]"; +var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`; +var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`; +var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]"; +var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]"; +var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]"; +var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR; +var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`; +var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`; +var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`; +var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`; +var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`; +var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT; +var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`; +var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`; +var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`; +var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u"); +var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u"); +var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u"); +var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u"); +var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u"); +var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u"); +var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u"); +var DEFAULT_PRESENTER_OPTIONS = { + indent: 2, + seqNoIndent: false, + seqInlineFirst: true, + lineWidth: 80, + flowBracketPadding: false, + flowSkipCommaSpace: false, + flowSkipColonSpace: false, + quoteFlowKeys: false, + quoteStyle: "single", + forceQuotes: false, + scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)), + tagBeforeAnchor: false +}; +var DEFAULT_DUMP_OPTIONS = { + ...DEFAULT_PRESENTER_OPTIONS, + schema: DUMP_SCHEMA, + skipInvalid: false, + noRefs: false, + flowLevel: -1, + sortKeys: false, + transform: () => { + } +}; +var EVENT_DOCUMENT = EVENT_ID.DOCUMENT; +var EVENT_SEQUENCE = EVENT_ID.SEQUENCE; +var EVENT_MAPPING = EVENT_ID.MAPPING; +var EVENT_SCALAR = EVENT_ID.SCALAR; +var EVENT_ALIAS = EVENT_ID.ALIAS; +var EVENT_POP = EVENT_ID.POP; +var SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN; +var SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED; +var SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED; +var SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK; +var SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK; +var COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK; +var COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW; +var CHOMPING_CLIP = CHOMPING_MODE.CLIP; +var CHOMPING_STRIP = CHOMPING_MODE.STRIP; +var CHOMPING_KEEP = CHOMPING_MODE.KEEP; + +// src/skill-scripts/shared/task-frontmatter.ts +var MAX_FRONTMATTER_BYTES = 64 * 1024; + +// src/skill-scripts/shared/task-file.ts +var extractFrontmatter = (content) => { + const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); + return match && match[1] ? match[1] : null; +}; + +// src/skill-scripts/shared/task-complexity.ts +var validateTaskComplexityScores = (planDir) => { + const tasksDir = path5.join(planDir, "tasks"); + if (!fs6.existsSync(tasksDir)) return []; + let files; + try { + if (!fs6.lstatSync(tasksDir).isDirectory()) return []; + files = fs6.readdirSync(tasksDir).filter((f) => f.endsWith(".md")).sort(); + } catch (_err) { + return []; + } + const invalid = []; + for (const file of files) { + let content; + try { + content = fs6.readFileSync(path5.join(tasksDir, file), "utf8"); + } catch (_err) { + invalid.push(`${file}: unreadable`); + continue; + } + const frontmatter = extractFrontmatter(content); + const match = frontmatter ? frontmatter.match(/^\s*complexity_score\s*:\s*(.*?)\s*(?:#.*)?$/im) : null; + if (!match || match[1] === void 0) { + invalid.push(`${file}: missing complexity_score`); + continue; + } + const raw = match[1].trim(); + const result = validateComplexityScore(raw); + if (result.valid) continue; + if (result.reason === "non-integer") { + invalid.push(`${file}: non-integer complexity_score "${raw}"`); + continue; + } + invalid.push(`${file}: complexity_score ${result.value} out of range 1-10`); + } + return invalid; +}; + +// src/skill-scripts/validate-plan-blueprint.ts +var VALID_FIELDS = [ + "planFile", + "planDir", + "taskCount", + "blueprintExists", + "strikethrooRoot", + "planId", + "complexityScoresValid", + "invalidComplexityTasks" +]; +var usage = () => { + const lines = [ + "Plan ID or absolute path is required", + "", + "Usage: node validate-plan-blueprint.cjs [field-name]", + "", + "Examples:", + " node validate-plan-blueprint.cjs 47", + " node validate-plan-blueprint.cjs /path/to/plan.md", + " node validate-plan-blueprint.cjs 47 planFile", + " node validate-plan-blueprint.cjs 47 blueprintExists" + ]; + lines.forEach((l) => process.stderr.write(`[ERROR] ${l} +`)); +}; +var listAvailablePlans = (startPath) => { + const tmRoot = findStrikethrooRoot(startPath); + if (!tmRoot) return []; + const plans = getAllPlans(tmRoot); + return plans.map((p) => p.name).sort((a, b) => { + const aMatch = a.match(/^(\d+)--/); + const bMatch = b.match(/^(\d+)--/); + if (!aMatch || !bMatch || !aMatch[1] || !bMatch[1]) return 0; + return parseInt(aMatch[1], 10) - parseInt(bMatch[1], 10); + }); +}; +var main = () => { + const inputId = process.argv[2]; + const fieldName = process.argv[3]; + if (!inputId) { + usage(); + process.exit(1); + } + if (_classifyPlanInput(inputId).kind === "invalid") { + process.stderr.write(`[ERROR] Invalid plan ID: "${inputId}" is not a valid number +`); + process.exit(1); + } + const resolved = resolvePlan(inputId); + if (!resolved) { + process.stderr.write(`[ERROR] Plan ID ${inputId} not found or invalid +`); + process.stderr.write("[ERROR] \n"); + const available = listAvailablePlans(process.cwd()); + if (available.length > 0) { + process.stderr.write("[ERROR] Available plans:\n"); + available.forEach((name) => process.stderr.write(`[ERROR] ${name} +`)); + } + process.exit(1); + } + const invalidComplexity = validateTaskComplexityScores(resolved.planDir); + const result = { + planFile: resolved.planFile, + planDir: resolved.planDir, + strikethrooRoot: resolved.strikethrooRoot, + planId: resolved.planId, + taskCount: countTaskFiles(resolved.planDir), + blueprintExists: hasExecutionBlueprint(resolved.planFile) ? "yes" : "no", + complexityScoresValid: invalidComplexity.length === 0 ? "yes" : "no", + invalidComplexityTasks: invalidComplexity.join("; ") + }; + if (fieldName) { + if (!VALID_FIELDS.includes(fieldName)) { + process.stderr.write(`[ERROR] Invalid field name: ${fieldName} +`); + process.stderr.write(`[ERROR] Valid fields: ${VALID_FIELDS.join(", ")} +`); + process.exit(1); + } + const value = result[fieldName]; + process.stdout.write(`${String(value)} +`); + } else { + process.stdout.write(`${JSON.stringify(result, null, 2)} +`); + } + process.exit(0); +}; +if (require.main === module) { + main(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + main +}); +/*! Bundled license information: + +js-yaml/dist/js-yaml.mjs: + (*! js-yaml 5.4.2 https://github.com/nodeca/js-yaml @license MIT *) +*/ diff --git a/.ai/strikethroo/.gitignore b/.ai/strikethroo/.gitignore new file mode 100644 index 0000000..7dc7761 --- /dev/null +++ b/.ai/strikethroo/.gitignore @@ -0,0 +1,33 @@ +# Local workspace configuration. +# +# Harness permissions, model routing, and resolver settings depend on the +# developer's machine. Init still creates and hash-tracks this file so re-runs +# can preserve local edits and report template conflicts. +config/config.yaml + +# Code review gate artifacts. +# +# The report-only review gate writes a recorded base commit and review.xml into +# the plan it is reviewing. A failed review may also leave reviewer-output.txt +# for diagnosis. These files are machine-generated output for one execution. +# +# Ignoring it also keeps the gate from reviewing itself. The reviewed diff runs +# from the recorded base against the working tree, and untracked files are in +# scope. The gate synthesizes an add-diff for each one. These rules keep its own +# output out because the gate enumerates untracked paths with +# `git ls-files --others --exclude-standard`. +# +# Both locations are listed because a completed plan directory is moved from +# plans/ to archive/ wholesale, carrying its review/ directory with it. +plans/*/review/ +archive/*/review/ + +# Dispatch-availability cache. +# +# The dispatch target selector probes external harnesses and caches each +# outcome here, with a lifetime measured in minutes. It is machine-generated, +# host-specific, and never meaningful to another checkout. The directory is +# created on demand by the first probe, so it can appear in a workspace long +# after init ran — which is why it is covered from here rather than by an +# ignore file shipped inside it. +runtime/ diff --git a/.ai/strikethroo/.init-metadata.json b/.ai/strikethroo/.init-metadata.json new file mode 100644 index 0000000..ab20cb9 --- /dev/null +++ b/.ai/strikethroo/.init-metadata.json @@ -0,0 +1,33 @@ +{ + "version": "4.1.1", + "workspaceSchemaVersion": 4, + "timestamp": "2026-10-08T18:14:33.511Z", + "files": { + "config/hooks/POST_ERROR_DETECTION.md": "a8d17efccf8c88f539c22fa9d031d64ff106130280752896a67d4115471846c1", + "config/hooks/POST_EXECUTION.md": "5fa68acecf31546dfd4fa27d311ff48b1194f7207cc22639d302541ec3e6caf2", + "config/hooks/POST_PHASE.md": "bc93df1dd0c4569efbef262cb6391708272f554fcbcc874ece76787db2b2b2ff", + "config/hooks/POST_PLAN.md": "4aa55bab300db517f3a7712a1c6cdb6d4acf9098db6f128a64a1c0975627240e", + "config/hooks/POST_TASK_GENERATION_ALL.md": "dacf8bd3c5c53fbc6bc6bc1b3f48c951bfba0372de4405fe09322ef3b95b0659", + "config/hooks/PRE_PHASE.md": "18aa062a375a9446f9ba6ebb6e8bba3e5ccb96ce4eaa4abbb10f43b846de9032", + "config/hooks/PRE_PLAN.md": "821a4730ecf3a4fdaafcdca4e17c93f207db8bd68ee20210e5a2f3092b8beaab", + "config/hooks/PRE_TASK_ASSIGNMENT.md": "03f6c50926ccb7460c4849cff9297f35b569695ca634d31adb91ad96cf30a1c1", + "config/templates/BLUEPRINT_TEMPLATE.md": "22184bbf3fb78323526a1ca5f314c838cbcbf01341572cc280cf31db0884a40b", + "config/templates/EXECUTION_SUMMARY_TEMPLATE.md": "ffc5329f070b10088be0ad17c67b98468a6e850cbb9749755bbc6a275e78ab35", + "config/templates/PLAN_TEMPLATE.md": "714115b5c3c3d4f6ddc281cbc7ea3872f1e436654d4a2442ce64b051ceb83870", + "config/templates/TASK_TEMPLATE.md": "89e52d079f17d23664e5a56b2bff018279e9b2e10e15a0ea9e2ab7b19327e341", + "config/STRIKETHROO.md": "98331dd4834b916d0b603263ac8d8306a6591bfd5889ea83873b04c3b0437177", + "config/config.yaml": "54abc3902467b06ffec98205934628933b99e511e51df53a8f6abcbe6a14a0d1", + "config/hooks/CODE_REVIEW.md": "bd4371d39eccbb04bdc0953103e79f51a287cef71300654d54dade0c0c429acc", + "config/hooks/PRE_TASK_EXECUTION.md": "9641a1bdd70aea5a13ae53ecf01263a93a63727775dc86e26a54a52f34f1fca0", + "config/hooks/TASK_EXECUTION_ROUTING.md": "d4d335937a349bf22b3f623eccb4a899929f4c9f1956b0d7257da7f006e827a7", + "config/schemas/self-review-v2.xsd": "acfb96ca3cf0411bbb15aa3f08bb3bf524985bdf5ca05c690c699e6956161d33", + "config/shared/anti-rationalization.md": "0d2c1a5c5efc39acdf05fcd9578d64bf43cdf602693085e3cf33fe2e9f69edb5", + "config/shared/clarification-gate.md": "73f61cf5ea8b91c638dcb84a643af399c662014b1e05cd3b3a4a55aa7c773233", + "config/shared/verification-gate.md": "002c6c5265e9612e64521172d99c49c8968d78ac6df907cdb352cc2b5d794ffd", + "config/templates/UPDATE_NOTICE_TEMPLATE.md": "3dc8a87667f609f88db968c3a82fc20f8b59054b93e8562d52aeb47681b8cc89" + }, + "harnesses": [ + "claude", + "codex" + ] +} diff --git a/.ai/strikethroo/README.md b/.ai/strikethroo/README.md new file mode 100644 index 0000000..5726948 --- /dev/null +++ b/.ai/strikethroo/README.md @@ -0,0 +1,7 @@ +# Strikethroo + +This directory contains AI-assisted task management files for this project. + +Managed by the [Strikethroo](https://www.github.com/e0ipso/strikethroo) project. + +**Documentation**: https://strikethroo.canpicasoft.com diff --git a/.ai/task-manager/config/TASK_MANAGER.md b/.ai/strikethroo/config/STRIKETHROO.md similarity index 85% rename from .ai/task-manager/config/TASK_MANAGER.md rename to .ai/strikethroo/config/STRIKETHROO.md index fd1bca1..d6934b9 100644 --- a/.ai/task-manager/config/TASK_MANAGER.md +++ b/.ai/strikethroo/config/STRIKETHROO.md @@ -1,7 +1,7 @@ -# Task Manager General Information +# Strikethroo General Information -This document contains important information that is common to all the /task:* -commands for AI assistants. +This document contains important information that is common to all the +Strikethroo skills your AI assistant uses to plan, decompose, and execute work. ## Types of Documents @@ -23,17 +23,17 @@ task cannot be worked on (or completed) before some other task(s) are completed. To find a plan document from its ID use the following command (replace {planId} with the ID, like 06): ```shell -find .ai/task-manager/{plans,archive} -name "plan-[0-9][0-9]*--*.md" -type f -exec grep -l "^id: \?{planId}$" {} \; +find .ai/strikethroo/{plans,archive} -name "plan-[0-9][0-9]*--*.md" -type f -exec grep -l "^id: \?{planId}$" {} \; ``` Plans, and tasks are stored as MarkDown files with a YAML front-matter. They are -all filed under the `.ai/task-manager/` folder at the root of the repository. +all filed under the `.ai/strikethroo/` folder at the root of the repository. Plans are organized as follows: ``` .ai/ - task-manager/ + strikethroo/ plans/ # Active plans (work in progress) 01--authentication-provider/ plan-01--authentication-provider.md @@ -52,7 +52,7 @@ Plans are organized as follows: 03--add-validation.md ``` -Note how in the `.ai/task-manager/plans/` folder we have a sub-folder per plan. +Note how in the `.ai/strikethroo/plans/` folder we have a sub-folder per plan. Each sub-folder will contain the plan document and has a name following a naming pattern `[ID]--[plan-short-name]`. Where the ID is auto-incremental. The plan document has a name following the pattern `plan-[ID]--[plan-short-name].md`. @@ -66,7 +66,7 @@ Plans follow a lifecycle that maintains workspace organization: 1. **Active Plans**: When created, plans are placed in the `plans/` directory where they remain while being worked on. -2. **Completed Plans**: Upon successful execution of a blueprint (via `/tasks:execute-blueprint`), the entire plan directory is automatically moved from `plans/` to `archive/`. +2. **Completed Plans**: Upon successful execution of a blueprint (via the `st-execute-blueprint` skill), the entire plan directory is automatically moved from `plans/` to `archive/`. 3. **Archive Directory**: The `archive/` directory serves as permanent storage for completed work. This separation keeps the active workspace clean while preserving completed plans for reference. diff --git a/.ai/strikethroo/config/hooks/CODE_REVIEW.md b/.ai/strikethroo/config/hooks/CODE_REVIEW.md new file mode 100644 index 0000000..b4bef95 --- /dev/null +++ b/.ai/strikethroo/config/hooks/CODE_REVIEW.md @@ -0,0 +1,50 @@ +# CODE_REVIEW Hook + +## Automated Code Review Gate + +This hook governs a review step that runs at the end of blueprint execution, after the mechanical gates (lint, tests, Self Validation) report success. A reviewer on a discovered external harness critiques the plan's cumulative diff and emits findings. The findings are validated against the vendored schema and recorded. + +The gate reports; it does not decide. Nothing is applied automatically, and the implementer reads the recorded findings and chooses what to act on. + +## Mandate: Conformance and Defects Only + +The reviewer checks the diff against the **plan's stated requirements** and for **demonstrable defects**. It does **not** raise general code-quality opinions, style notes, design critiques, or taste judgments. The linter owns style. Every finding must cite concrete evidence and trace to: + +- An explicit requirement stated in the plan, **or** +- A demonstrable defect in the code as written + +Anything else is out of scope and must not be included in findings. + +## Finding Categories In Scope + +- **Requirement conformance**: the code does not implement what the plan explicitly asked for +- **Demonstrable defects**: the code fails at runtime, produces wrong behaviour, violates a contract it declares, has a security hole, causes data loss, or breaks something else in the plan + +## Severity and Confidence + +Both are advisory triage labels carried on every finding so that whoever reads the review can sort it. Nothing thresholds on them and nothing is filtered out before the implementer sees it. + +Severity, from most to least consequential: + +- `critical`: causes data loss, a security hole, a crash, or corruption on a path real usage reaches +- `major`: produces wrong behaviour or breaks a documented contract; nothing destroyed +- `minor`: real but bounded (mishandled edge case, maintenance hazard); behaviour correct today +- `info`: no defect (recorded context, a question for the author) + +Confidence, from most to least sure: + +- `high`: the evidence is in the code that was read, and the failure traces from the diff alone +- `medium`: likely real, but rests on one assumption that was not verified (how a caller behaves, what a dependency guarantees, what a requirement was) +- `low`: speculative (failure scenario imagined rather than traced, constraint invented, intent could not be inferred) + +Confidence matters most when it is low. LLM reviewers overstate certainty, so a reviewer that marks its own guess as `medium` is doing the reader a service. Record the label honestly rather than upgrading it to be taken seriously. + +## What the Gate Guarantees + +Exactly one thing, and it is enforced in code rather than here: a review that could not be certified is never reported as a clean one. A findings document that is absent, invalid against the schema, or unvalidatable because `xmllint` is missing halts the gate and says which of those happened. "The reviewer found nothing" and "the reviewer never ran" are never collapsed into each other. + +## Disable the Gate + +**Emptying this file, or deleting it, disables the review gate cleanly.** The gate skips with no error and records the skip in the execution summary. This is the documented sentinel for "do not review this plan"; there is no undefined behaviour and no error. + +Users who already have a code review step in their workflow disable this feature by editing or emptying the hook, matching the pattern of `PRE_TASK_EXECUTION` which ships an overridable default discipline. diff --git a/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md b/.ai/strikethroo/config/hooks/POST_ERROR_DETECTION.md similarity index 86% rename from .ai/task-manager/config/hooks/POST_ERROR_DETECTION.md rename to .ai/strikethroo/config/hooks/POST_ERROR_DETECTION.md index ba2effb..a41786a 100644 --- a/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md +++ b/.ai/strikethroo/config/hooks/POST_ERROR_DETECTION.md @@ -1,7 +1,5 @@ # POST_ERROR_DETECTION Hook -This hook provides error handling procedures for task execution failures and validation gate failures. - ## Task Execution Error Handling If task execution fails: @@ -45,4 +43,4 @@ If validation gates fail: 3. Generate remediation plan 4. Re-execute affected tasks after fixes 5. Re-run validation gates -6. If errors persist, escalate to the user \ No newline at end of file +6. If errors persist, escalate to the user diff --git a/.ai/task-manager/config/hooks/POST_EXECUTION.md b/.ai/strikethroo/config/hooks/POST_EXECUTION.md similarity index 72% rename from .ai/task-manager/config/hooks/POST_EXECUTION.md rename to .ai/strikethroo/config/hooks/POST_EXECUTION.md index 6556d2b..9a25926 100644 --- a/.ai/task-manager/config/hooks/POST_EXECUTION.md +++ b/.ai/strikethroo/config/hooks/POST_EXECUTION.md @@ -10,6 +10,11 @@ Before marking the blueprint as complete, verify: - [ ] Verify that the AGENTS.md documentation or related documentes are still correct after this plan execution - [ ] Execute the **Self Validation** steps defined in the plan document. These are concrete verification procedures (e.g., Playwright browser checks, database CLI queries, screenshots) that confirm the implementation works in the real system. If any step fails, treat it as a validation gate failure +## Cleanup +Assess weather the current plan has left tech debt behind or if it has created dead code. None of those are acceptable. Fix them and leave behind the most maintainable code change possible. + +Backwards compatibility and legacy support are only tolerated if explicitly expressed by the user. Unless it is called out in the plan, you are to assume that backwards compatibility layers are tech debt that should be eliminated. + ## Failure Behavior If any validation gate fails: diff --git a/.ai/task-manager/config/hooks/POST_PHASE.md b/.ai/strikethroo/config/hooks/POST_PHASE.md similarity index 72% rename from .ai/task-manager/config/hooks/POST_PHASE.md rename to .ai/strikethroo/config/hooks/POST_PHASE.md index 8fde79c..e0635fc 100644 --- a/.ai/task-manager/config/hooks/POST_PHASE.md +++ b/.ai/strikethroo/config/hooks/POST_PHASE.md @@ -1,9 +1,11 @@ # POST_PHASE Hook -Ensure that: +## Phase Post-Execution - - The code base is passing the linting requirements - - A descriptive commit (using conventional commits with a subject and a description) for the phase was successfully created. +Before moving to the next phase: + +- Run lint and/or format checks if this hook defines them for your project. If none are defined here, skip this step. +- Create a descriptive conventional commit for the phase (subject and body). ### Execution Monitoring @@ -21,4 +23,3 @@ Valid status transitions: - `in-progress` → `completed` (successful execution) - `in-progress` → `failed` (execution error) - `failed` → `in-progress` (retry attempt) - diff --git a/.ai/strikethroo/config/hooks/POST_PLAN.md b/.ai/strikethroo/config/hooks/POST_PLAN.md new file mode 100644 index 0000000..5f9b75c --- /dev/null +++ b/.ai/strikethroo/config/hooks/POST_PLAN.md @@ -0,0 +1,5 @@ +# POST_PLAN Hook + +Ensure the plan includes a _Self Validation_ section describing the steps the LLM will take to validate that the plan was completed successfully. + +Also, answer the question _Does this plan need to update the documentation, or the AGENTS.md_. diff --git a/.ai/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md b/.ai/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md new file mode 100644 index 0000000..e646a76 --- /dev/null +++ b/.ai/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md @@ -0,0 +1,31 @@ +# POST_TASK_GENERATION_ALL Hook + +After all tasks have been generated, update the plan with the execution blueprint. + +## 1. Update Plan with Blueprint + +Append to the plan document: + +### Dependency Diagram + +If tasks have dependencies, add a Mermaid graph: + +```mermaid +graph TD + 001[Task 001: Description] --> 002[Task 002: Description] +``` + +Verify there are no circular dependencies. + +### Execution Phases + +Group tasks into phases: +- **Phase 1**: Tasks with no dependencies (run in parallel) +- **Phase N**: Tasks whose dependencies are all in earlier phases + +Use the template in `.ai/strikethroo/config/templates/BLUEPRINT_TEMPLATE.md` for structure. + +Before finalizing, verify: +- Every task is in exactly one phase +- No task runs before its dependencies complete +- Phase 1 has only zero-dependency tasks diff --git a/.ai/strikethroo/config/hooks/PRE_PHASE.md b/.ai/strikethroo/config/hooks/PRE_PHASE.md new file mode 100644 index 0000000..fccdd1e --- /dev/null +++ b/.ai/strikethroo/config/hooks/PRE_PHASE.md @@ -0,0 +1,8 @@ +# PRE_PHASE Hook + +## Phase Pre-Execution + +1. **Phase Initialization** + - Identify current phase from the execution blueprint + - List all tasks scheduled for parallel execution in this phase + - If any phases are marked as completed, verify they are actually completed and continue from the next phase. diff --git a/.ai/task-manager/config/hooks/PRE_PLAN.md b/.ai/strikethroo/config/hooks/PRE_PLAN.md similarity index 89% rename from .ai/task-manager/config/hooks/PRE_PLAN.md rename to .ai/strikethroo/config/hooks/PRE_PLAN.md index 2283b8d..b116c7d 100644 --- a/.ai/task-manager/config/hooks/PRE_PLAN.md +++ b/.ai/strikethroo/config/hooks/PRE_PLAN.md @@ -1,7 +1,5 @@ # PRE_PLAN Hook -This hook provides pre-planning guidance to ensure scope control, simplicity principles, and proper validation requirements are established before comprehensive plan creation. - ## Scope Control Guidelines **Critical: Implement ONLY what is explicitly requested** @@ -40,5 +38,5 @@ This hook provides pre-planning guidance to ensure scope control, simplicity pri - Never generate a partial or assumed plan without adequate context - Prioritize accuracy over speed - Consider both technical and non-technical aspects -- Use the plan template in .ai/task-manager/config/templates/PLAN_TEMPLATE.md +- Use the plan template in .ai/strikethroo/config/templates/PLAN_TEMPLATE.md - DO NOT create or list any tasks or phases during the plan creation. This will be done in a later step. Stick to writing the PRD (Project Requirements Document). diff --git a/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md b/.ai/strikethroo/config/hooks/PRE_TASK_ASSIGNMENT.md similarity index 51% rename from .ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md rename to .ai/strikethroo/config/hooks/PRE_TASK_ASSIGNMENT.md index 1f3900d..c6d3538 100644 --- a/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md +++ b/.ai/strikethroo/config/hooks/PRE_TASK_ASSIGNMENT.md @@ -1,7 +1,5 @@ # PRE_TASK_ASSIGNMENT Hook -This hook executes before task assignment to determine the most appropriate agent for each task based on skill requirements and available sub-agents. - ## Agent Selection and Task Assignment - For each task in the current phase: @@ -11,12 +9,12 @@ This hook executes before task assignment to determine the most appropriate agen - Select the most appropriate sub-agent (if any are available). If no sub-agent is appropriate, use the general-purpose one. - Consider task-specific requirements from the task document -[IMPORTANT] Analyze the set of tasks skills in order to engage any relevant assistant skills as necessary (either global +[IMPORTANT] Analyze the set of tasks skills in order to engage any relevant harness skills as necessary (either global or project skills). ## Available Sub-Agents -Analyze the sub-agents available in your current assistant's agents directory. If none are available or the available +Analyze the sub-agents available in your current harness's agents directory. If none are available or the available ones do not match the task's requirements, then use a generic agent. ## Matching Criteria @@ -28,25 +26,7 @@ Select agents based on: ## Skills Extraction and Agent Detection -Read task skills and select appropriate task-specific agent: - -```bash -# Extract skills from task frontmatter -TASK_SKILLS=$(node "$root/config/scripts/extract-task-skills.cjs" "$TASK_FILE") - -echo "Task skills required: $TASK_SKILLS" - -# Check for available sub-agents across assistant directories -AGENT_FOUND=false -for assistant_dir in .claude .gemini .opencode; do - if [ -d "$assistant_dir/agents" ] && [ -n "$(ls $assistant_dir/agents 2>/dev/null)" ]; then - echo "Available sub-agents detected in $assistant_dir - will match to task requirements" - AGENT_FOUND=true - break - fi -done - -if [ "$AGENT_FOUND" = false ]; then - echo "Using general-purpose agent for task execution" -fi -``` +1. Read the `skills` array from the task's YAML frontmatter directly. +2. Check for available sub-agents in your harness's agents directory. +3. If matching sub-agents are found, select the most appropriate one based on the task's required skills. +4. If no sub-agents are available or none match, use a general-purpose agent for task execution. diff --git a/.ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md b/.ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md new file mode 100644 index 0000000..478f15f --- /dev/null +++ b/.ai/strikethroo/config/hooks/PRE_TASK_EXECUTION.md @@ -0,0 +1,15 @@ +# PRE_TASK_EXECUTION Hook + +## Test-Driven Development: RED → GREEN → REFACTOR + +Before writing production code for this task, follow this cycle for each increment: + +1. **RED** — Write one failing test and run it; confirm it fails for the + expected reason. +2. **GREEN** — Write the minimal code to pass it (YAGNI); confirm it passes. +3. **REFACTOR** — Clean up with the test green; re-run and confirm still green. + +Apply this only to the meaningful tests the test philosophy calls for (custom +logic, critical paths, edge cases) — not to trivial, CRUD, or framework code. +If a task warrants no new test under that philosophy, state why and implement +directly. diff --git a/.ai/strikethroo/config/hooks/TASK_EXECUTION_ROUTING.md b/.ai/strikethroo/config/hooks/TASK_EXECUTION_ROUTING.md new file mode 100644 index 0000000..a7c68f7 --- /dev/null +++ b/.ai/strikethroo/config/hooks/TASK_EXECUTION_ROUTING.md @@ -0,0 +1,30 @@ +# TASK_EXECUTION_ROUTING Hook + +Runs during task generation, after every task file for the plan exists and +before the execution blueprint is generated. + +## Classification contract + +- Execution profiles are defined in the `execution_routing` section of + `.ai/strikethroo/config/config.yaml`. Their descriptions are the + routing contract: match each newly generated task against them using the + full task content already in your context — `skills`, `complexity_score`, + objective, acceptance criteria, technical requirements, and integration + surface. Do not reread task files to reconstruct information you already + have. +- Classify every generated task exactly once, using only configured profile + names. Never guess or invent a model, harness, or profile name. +- The task-to-profile mapping file is temporary. The selected profile name is + durable task metadata, persisted by the routing helper as exactly one + `execution_profile` field. Concrete execution targets are selected later at + task dispatch and are never persisted during generation. +- Any routing failure aborts task generation before blueprint generation. + Never continue with partially routed tasks. + +## Project-specific guidance + +Add project-specific classification guidance here, for example: + +- Prefer the most capable profile for tasks touching authentication, + payments, or data migrations. +- Treat documentation-only or configuration-only tasks as routine work. diff --git a/.ai/strikethroo/config/schemas/self-review-v2.xsd b/.ai/strikethroo/config/schemas/self-review-v2.xsd new file mode 100644 index 0000000..c0d4274 --- /dev/null +++ b/.ai/strikethroo/config/schemas/self-review-v2.xsd @@ -0,0 +1,416 @@ + + + + + + + + + + + Root element of a self-review output file. Contains one file element + per file in the git diff, including files with no comments. + + + + + + + + + + + + + + ISO 8601 timestamp of when the review was completed (window closed). + + + + + + + The git diff arguments that were passed to self-review on the CLI. + Example: "--staged", "main..feature-branch", "HEAD~3". + Present only when reviewing a git diff. + + + + + + + Absolute path to the repository root where self-review was invoked. + Present only when reviewing a git diff. + + + + + + + Absolute path to the directory being reviewed. + Present only when reviewing a directory (non-git mode). + + + + + + + + + Represents a single file in the diff. Files with no comments + appear as empty elements. The path is relative to the repository root. + + + + + + + + + File path relative to the repository root. For renamed files, + this is the new path. + + + + + + + The type of change: added, modified, deleted, or renamed. + + + + + + + Whether the reviewer marked this file as reviewed. + true = the reviewer looked at this file. + false = the reviewer did not mark this file as viewed. + This helps an AI agent distinguish "reviewed with no comments" + from "not yet reviewed." + + + + + + + + + A review comment. Three forms: + + 1. File-level comment: no line attributes present. + Applies to the file as a whole. + + 2. Comment on new/added/context lines: new-line-start and + new-line-end are present. These reference line numbers in the + post-change version of the file. + + 3. Comment on old/deleted lines: old-line-start and old-line-end + are present. These reference line numbers in the pre-change + version of the file. + + For single-line comments, start and end are equal. + Exactly one pair (old or new) should be present for line-level + comments. Both pairs absent = file-level comment. + + The category child says what kind of finding this is. Severity and + confidence are independent advisory labels for a human reader; + nothing branches on them. + + + + + + + The comment text. May contain markdown formatting. + + + + + + + Required category tag for this comment (e.g., "bug", "style", + "nit", "question", "security"). Categories are defined in the + project-level .self-review.yaml configuration. Every comment + must have a category to help AI agents prioritize and triage + feedback. + + + + + + + Optional code replacement proposal. When present, the AI agent + should replace the original-code with the proposed-code at the + referenced line range. + + + + + + + Optional image attachment. The path attribute references an image file + stored in the .self-review-assets/ directory alongside the XML output. + + + + + + + + Start line number in the pre-change (old) version of the file. + Use for comments on deleted lines. + + + + + + + End line number (inclusive) in the pre-change (old) version. + Must be >= old-line-start when both are present. + + + + + + + Start line number in the post-change (new) version of the file. + Use for comments on added or context (unchanged) lines. + + + + + + + End line number (inclusive) in the post-change (new) version. + Must be >= new-line-start when both are present. + + + + + + + The author of this comment. When present, indicates the comment + was generated by a bot or LLM (e.g., "Claude Sonnet 4.6"). + When absent, the comment is assumed to be authored by the human + reviewer. + + + + + + + How consequential this finding is if real. Judge impact, not + confidence and not fix effort. No schema default: absence is + meaningful. Human-written comments normally carry none. + + + + + + + How sure the author is that this finding is real. Judge the + evidence, not the wording: an argument resting on a constraint not + visible in the diff, an unread caller, or an untraced scenario is + low confidence. LLM reviewers overstate certainty here. No schema + default: absence is meaningful. + + + + + + + + + A code replacement proposal. The original-code is the literal text + currently at the referenced lines. The proposed-code is what the + reviewer suggests it should be replaced with. The AI agent can apply + this by performing a text substitution. + + + + + + + The existing code at the referenced line range, copied verbatim + from the diff. Used by the AI agent to locate the replacement + target via text matching. + + + + + + + The replacement code proposed by the reviewer. The AI agent + should substitute original-code with this text. + + + + + + + + + + Reference to an image file attached to a review comment. The file is stored + alongside the XML output in the .self-review-assets/ directory. + + + + + Relative path from the XML file to the image file. + + + + + MIME type of the image (e.g., image/png, image/jpeg). + + + + + + + + + + The type of change a file underwent in the diff. + + + + + + New file that did not exist before. + + + + + Existing file with content changes. + + + + + File was removed. + + + + + File was moved or renamed, with or without content changes. + + + + + + + + + How consequential a finding is if it is real. Ordered from most to + least consequential: critical, major, minor, info. + + + + + + + Causes data loss, a security hole, or a crash or corruption on a + path that real usage reaches. Shipping this is not acceptable. + + + + + + + Produces wrong behaviour, or breaks a documented contract, on a + path that real usage reaches. The code does not do what it is + supposed to do, but nothing is destroyed and there is no security + impact. + + + + + + + Real but bounded: a mishandled edge case that is unlikely to be + hit, a missing test, a leak of something cheap, or a maintenance + hazard that will cost time later. Behaviour is correct today. + + + + + + + No defect. Style, naming, phrasing, a question for the author, or + a note recorded for context. Nothing is wrong if this is never + acted on. + + + + + + + + + + How sure the author is that a finding is real. Ordered from most to + least sure: high, medium, low. + + + + + + + The evidence is in the code that was read. The failure can be + traced from the diff itself, and no assumption about unseen code, + unseen callers, or unstated requirements is needed to reach it. + + + + + + + Likely real, but it rests on one assumption that was not verified, + such as how a caller behaves, what a dependency guarantees, or + what the intended requirement was. Stating that assumption in the + body is expected at this level. + + + + + + + Speculative. The failure scenario was imagined rather than traced, + or the finding depends on a constraint the author invented, or the + author could not tell intent from the code. Worth a human's eyes, + not worth acting on unattended. + + + + + + + diff --git a/.ai/strikethroo/config/shared/anti-rationalization.md b/.ai/strikethroo/config/shared/anti-rationalization.md new file mode 100644 index 0000000..37e8029 --- /dev/null +++ b/.ai/strikethroo/config/shared/anti-rationalization.md @@ -0,0 +1,3 @@ +# Anti-rationalization + +A discipline survives pressure only if you refuse the excuse to skip it. When a thought in the "rationalization" column of the skill's table forms, treat it as a red flag and apply the binding rule instead. There is no "unless it matters" exception. diff --git a/.ai/strikethroo/config/shared/clarification-gate.md b/.ai/strikethroo/config/shared/clarification-gate.md new file mode 100644 index 0000000..baf7739 --- /dev/null +++ b/.ai/strikethroo/config/shared/clarification-gate.md @@ -0,0 +1,7 @@ +# Clarification Gate — Cadence & Approval + +When you have questions: + +- **One at a time.** Ask a single question, wait for the answer, then decide the next from it — do not dump a batch. +- **Multiple-choice first.** When the question allows, offer options with a recommended default plus an open-ended "Other"; the user confirms in one word. +- **Approval gate.** Present the resolved scope and get explicit confirmation before you write or update the plan. diff --git a/.ai/strikethroo/config/shared/verification-gate.md b/.ai/strikethroo/config/shared/verification-gate.md new file mode 100644 index 0000000..55f22c4 --- /dev/null +++ b/.ai/strikethroo/config/shared/verification-gate.md @@ -0,0 +1,10 @@ +# Verification Gate — Evidence Before Claims + +Before stating that anything is complete, passing, or working: + +1. **IDENTIFY** the command or signal that proves the claim. +2. **RUN** it fresh now — never rely on earlier output or a subagent's report. +3. **READ** the full output and exit code. +4. **VERIFY** it matches the claim, then state the result. + +Red-flag words — "should", "probably", "seems to", "looks like", a premature "Done!" — mean you have not run the gate. Run it. diff --git a/.ai/task-manager/config/templates/BLUEPRINT_TEMPLATE.md b/.ai/strikethroo/config/templates/BLUEPRINT_TEMPLATE.md similarity index 87% rename from .ai/task-manager/config/templates/BLUEPRINT_TEMPLATE.md rename to .ai/strikethroo/config/templates/BLUEPRINT_TEMPLATE.md index 211aed2..c2b6590 100644 --- a/.ai/task-manager/config/templates/BLUEPRINT_TEMPLATE.md +++ b/.ai/strikethroo/config/templates/BLUEPRINT_TEMPLATE.md @@ -22,5 +22,3 @@ ### Execution Summary - Total Phases: X - Total Tasks: Y -- Maximum Parallelism: Z tasks (in Phase N) -- Critical Path Length: X phases diff --git a/.ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md b/.ai/strikethroo/config/templates/EXECUTION_SUMMARY_TEMPLATE.md similarity index 94% rename from .ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md rename to .ai/strikethroo/config/templates/EXECUTION_SUMMARY_TEMPLATE.md index 7da5296..1cfe296 100644 --- a/.ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md +++ b/.ai/strikethroo/config/templates/EXECUTION_SUMMARY_TEMPLATE.md @@ -9,5 +9,5 @@ ### Noteworthy Events [Highlight any unexpected events, challenges overcome, or significant findings during execution. If none occurred, state "No significant issues encountered."] -### Recommendations +### Necessary follow-ups [Any follow-up actions or optimizations identified] diff --git a/.ai/task-manager/config/templates/PLAN_TEMPLATE.md b/.ai/strikethroo/config/templates/PLAN_TEMPLATE.md similarity index 96% rename from .ai/task-manager/config/templates/PLAN_TEMPLATE.md rename to .ai/strikethroo/config/templates/PLAN_TEMPLATE.md index 4edd159..b218815 100644 --- a/.ai/task-manager/config/templates/PLAN_TEMPLATE.md +++ b/.ai/strikethroo/config/templates/PLAN_TEMPLATE.md @@ -89,7 +89,7 @@ Avoid vague statements like "verify it works" or "ensure quality". Each step mus ## Documentation -[Required documentation updates to existing documentation, either human-focused documentation, the project's README.md or assistant-focused documentation like AGENTS.md, .claude/skills/* for the site, etc.] +[Required documentation updates to existing documentation, either human-focused documentation like README.md or AI-facing documentation like AGENTS.md and related configuration files.] ## Resource Requirements diff --git a/.ai/task-manager/config/templates/TASK_TEMPLATE.md b/.ai/strikethroo/config/templates/TASK_TEMPLATE.md similarity index 82% rename from .ai/task-manager/config/templates/TASK_TEMPLATE.md rename to .ai/strikethroo/config/templates/TASK_TEMPLATE.md index a1e6792..34c32ed 100644 --- a/.ai/task-manager/config/templates/TASK_TEMPLATE.md +++ b/.ai/strikethroo/config/templates/TASK_TEMPLATE.md @@ -2,11 +2,14 @@ id: [TASK-ID] group: "user-authentication" dependencies: [] # List of task IDs, e.g., [2, 3] -status: "[STATUS]" # pending | in-progress | completed | needs-clarification +status: "[STATUS]" # pending | in-progress | completed | needs-clarification | failed created: [YYYY-MM-DD] skills: # Technical skills required for this task - [SKILL-1] - [SKILL-2] +complexity_score: [1-10] # Required on every newly generated task +# Optional configured routing profile, assigned atomically during task generation. +# execution_profile: "profile-name" --- # [TASK-TITLE] diff --git a/.ai/strikethroo/config/templates/UPDATE_NOTICE_TEMPLATE.md b/.ai/strikethroo/config/templates/UPDATE_NOTICE_TEMPLATE.md new file mode 100644 index 0000000..2146eb7 --- /dev/null +++ b/.ai/strikethroo/config/templates/UPDATE_NOTICE_TEMPLATE.md @@ -0,0 +1 @@ +A newer Strikethroo release is available. Run `{{updateCommand}}` to update. diff --git a/.ai/task-manager/plans/01--review-open-issues/plan-01--review-open-issues.md b/.ai/strikethroo/plans/01--review-open-issues/plan-01--review-open-issues.md similarity index 100% rename from .ai/task-manager/plans/01--review-open-issues/plan-01--review-open-issues.md rename to .ai/strikethroo/plans/01--review-open-issues/plan-01--review-open-issues.md diff --git a/.ai/task-manager/plans/01--review-open-issues/tasks/01--improve-install-playwright.md b/.ai/strikethroo/plans/01--review-open-issues/tasks/01--improve-install-playwright.md similarity index 100% rename from .ai/task-manager/plans/01--review-open-issues/tasks/01--improve-install-playwright.md rename to .ai/strikethroo/plans/01--review-open-issues/tasks/01--improve-install-playwright.md diff --git a/.ai/task-manager/plans/01--review-open-issues/tasks/02--document-show-report.md b/.ai/strikethroo/plans/01--review-open-issues/tasks/02--document-show-report.md similarity index 100% rename from .ai/task-manager/plans/01--review-open-issues/tasks/02--document-show-report.md rename to .ai/strikethroo/plans/01--review-open-issues/tasks/02--document-show-report.md diff --git a/.ai/task-manager/plans/01--review-open-issues/tasks/03--prepare-locale-feedback.md b/.ai/strikethroo/plans/01--review-open-issues/tasks/03--prepare-locale-feedback.md similarity index 100% rename from .ai/task-manager/plans/01--review-open-issues/tasks/03--prepare-locale-feedback.md rename to .ai/strikethroo/plans/01--review-open-issues/tasks/03--prepare-locale-feedback.md diff --git a/.ai/task-manager/plans/02--ci-standard-test-template/plan-02--ci-standard-test-template.md b/.ai/strikethroo/plans/02--ci-standard-test-template/plan-02--ci-standard-test-template.md similarity index 100% rename from .ai/task-manager/plans/02--ci-standard-test-template/plan-02--ci-standard-test-template.md rename to .ai/strikethroo/plans/02--ci-standard-test-template/plan-02--ci-standard-test-template.md diff --git a/.ai/task-manager/.init-metadata.json b/.ai/task-manager/.init-metadata.json deleted file mode 100644 index 5a0901b..0000000 --- a/.ai/task-manager/.init-metadata.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "1.32.0", - "timestamp": "2026-03-11T23:55:58.222Z", - "files": { - "config/TASK_MANAGER.md": "ad37290f6f5bced23be611198f288f8c196452183aa139197085c3da73174b49", - "config/hooks/POST_ERROR_DETECTION.md": "ed4e1691880ea54ea43c318dc236c326ed81a3ce2785321a25e6db747a6e7e88", - "config/hooks/POST_EXECUTION.md": "09241e85e98000a354357141ba468acf46283699529da1dfb837d037d4f6d297", - "config/hooks/POST_PHASE.md": "d79fccfee4629ffc226db97f6f755c4dd068ee9c30f7d8bf98dfc55b104003c5", - "config/hooks/POST_PLAN.md": "4c9850cb6d11d74065b6c4a00137fe00540aeea7b44d9edbfc8211ff5ea34662", - "config/hooks/POST_TASK_GENERATION_ALL.md": "f801cb9d32eeb22e97de903aa2f7ce7dd9ca13671ebc3a007ceffa1fc55e52ef", - "config/hooks/PRE_PHASE.md": "f679ee0ba65979c778b8613ff9743a4dcf87347671110f8e645604fe7a2508f5", - "config/hooks/PRE_PLAN.md": "c25f722a8cd507664683ee2b46a4b9f0518ef97c7fd438eb6d295fad55d9c3c6", - "config/hooks/PRE_TASK_ASSIGNMENT.md": "4c338542834807083be6eb76e67e30b04ad5edee34b25f002d84838009c76f8d", - "config/templates/BLUEPRINT_TEMPLATE.md": "f67488cd05a2fcdbf8a58a863d1315cde4f77a3b42d7e752374feb31620e8063", - "config/templates/EXECUTION_SUMMARY_TEMPLATE.md": "9023bd2f6e39169068fd8684254679c82bc76ddbde3d2881eadd76c107f083c2", - "config/templates/PLAN_TEMPLATE.md": "27c520562257e14d697ce7e97a01858f3f8bd4302bdb2afe49634e5ffb650e96", - "config/templates/TASK_TEMPLATE.md": "e0fa4d9bde7d9ab9edcf4f32785011c7125424f5199a0994c5900ef0352c4e02" - } -} \ No newline at end of file diff --git a/.ai/task-manager/README.md b/.ai/task-manager/README.md deleted file mode 100644 index 344c634..0000000 --- a/.ai/task-manager/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# AI Task Manager - -This directory contains AI-assisted task management files for this project. - -Managed by the [AI Task Manager](https://www.github.com/e0ipso/ai-task-manager) project. - -**Documentation**: https://mateuaguilo.com/ai-task-manager diff --git a/.ai/task-manager/config/hooks/POST_PLAN.md b/.ai/task-manager/config/hooks/POST_PLAN.md deleted file mode 100644 index 07359a6..0000000 --- a/.ai/task-manager/config/hooks/POST_PLAN.md +++ /dev/null @@ -1,3 +0,0 @@ -# POST_PLAN Hook - -This hook provides validation and update procedures to execute after plan creation, ensuring comprehensive context analysis and proper plan document structuring with dependency visualization. diff --git a/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md b/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md deleted file mode 100644 index 7368d14..0000000 --- a/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md +++ /dev/null @@ -1,41 +0,0 @@ -# POST_TASK_GENERATION_ALL Hook - -After all tasks have been generated, perform these two steps: - -## 1. Review Task Complexity - -For each generated task, do a quick sanity check: - -- **Too complex?** If a task spans 3+ technologies or requires 3+ skills, split it. -- **Too vague?** If acceptance criteria are unclear, sharpen them. -- **Too trivial?** If two tasks could be one without adding complexity, merge them. - -Target: every task should be completable with 1-2 skills and have clear acceptance criteria. - -## 2. Update Plan with Blueprint - -After finalizing tasks, append to the plan document: - -### Dependency Diagram - -If tasks have dependencies, add a Mermaid graph: - -```mermaid -graph TD - 001[Task 001: Description] --> 002[Task 002: Description] -``` - -Verify there are no circular dependencies. - -### Execution Phases - -Group tasks into phases: -- **Phase 1**: Tasks with no dependencies (run in parallel) -- **Phase N**: Tasks whose dependencies are all in earlier phases - -Use the template in `.ai/task-manager/config/templates/BLUEPRINT_TEMPLATE.md` for structure. - -Before finalizing, verify: -- Every task is in exactly one phase -- No task runs before its dependencies complete -- Phase 1 has only zero-dependency tasks diff --git a/.ai/task-manager/config/hooks/PRE_PHASE.md b/.ai/task-manager/config/hooks/PRE_PHASE.md deleted file mode 100644 index 482b21c..0000000 --- a/.ai/task-manager/config/hooks/PRE_PHASE.md +++ /dev/null @@ -1,43 +0,0 @@ -# PRE_PHASE Hook - -This hook contains the phase preparation logic that should be executed before starting any phase execution. - -## Phase Pre-Execution - -### Feature Branch Creation - -Create a feature branch for this plan execution (only runs from main/master with a clean working tree): - -```bash -# Create feature branch (handles all edge cases automatically) -node $root/config/scripts/create-feature-branch.cjs $1 - -# Exit codes: -# 0 = Success (branch created, already exists, or not on main/master) -# 1 = Error (not git repo, uncommitted changes, or plan not found) -``` - -**Behavior**: -- From `main`/`master` with clean tree: Creates `feature/{planId}--{plan-name}` branch -- From `main`/`master` with uncommitted changes: Exits with error (exit 1) -- From feature branch: Proceeds without creating a new branch -- Branch already exists: Proceeds normally - -## Phase Execution Workflow - -1. **Phase Initialization** - - Identify current phase from the execution blueprint - - List all tasks scheduled for parallel execution in this phase - - **Validate Task Dependencies**: For each task in the current phase, use the dependency checking script: - ```bash - # For each task in current phase - for TASK_ID in $PHASE_TASKS; do - if ! node .ai/task-manager/config/scripts/check-task-dependencies.cjs "$1" "$TASK_ID"; then - echo "ERROR: Task $TASK_ID has unresolved dependencies - cannot proceed with phase execution" - echo "Please resolve dependencies before continuing with blueprint execution" - exit 1 - fi - done - ``` - - Confirm no tasks are marked "needs-clarification" - - If any phases are marked as completed, verify they are actually completed and continue from the next phase. \ No newline at end of file diff --git a/.ai/task-manager/config/scripts/check-task-dependencies.cjs b/.ai/task-manager/config/scripts/check-task-dependencies.cjs deleted file mode 100755 index 06bc736..0000000 --- a/.ai/task-manager/config/scripts/check-task-dependencies.cjs +++ /dev/null @@ -1,240 +0,0 @@ -#!/usr/bin/env node - -/** - * Script: check-task-dependencies.cjs - * Purpose: Check if a task has all of its dependencies resolved (completed) - * Usage: node check-task-dependencies.cjs - * Returns: 0 if all dependencies are resolved, 1 if not - */ - -const fs = require('fs'); -const path = require('path'); -const { - resolvePlan, - parseFrontmatter -} = require('./shared-utils.cjs'); - -// Color functions for output -const _printError = (message) => { - console.error(`ERROR: ${message}`); -}; - -const _printSuccess = (message) => { - console.log(`✓ ${message}`); -}; - -const _printWarning = (message) => { - console.log(`⚠ ${message}`); -}; - -const _printInfo = (message) => { - console.log(message); -}; - -// Function to find task file with padded/unpadded ID handling -const _findTaskFile = (planDir, taskId) => { - const taskDir = path.join(planDir, 'tasks'); - - if (!fs.existsSync(taskDir)) { - return null; - } - - const variations = [ - taskId, - taskId.padStart(2, '0'), - taskId.replace(/^0+/, '') || '0' - ]; - - const uniqueVariations = [...new Set(variations)]; - - try { - const files = fs.readdirSync(taskDir); - const found = uniqueVariations.reduce((acc, v) => { - if (acc) return acc; - const match = files.find(f => f.startsWith(`${v}--`) && f.endsWith('.md')); - return match ? path.join(taskDir, match) : null; - }, null); - return found; - } catch (err) { - return null; - } -}; - - -// Function to extract dependencies from frontmatter -const _extractDependencies = (frontmatter) => { - const lines = frontmatter.split('\n'); - const dependencies = []; - let inDependenciesSection = false; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - // Check for dependencies line - if (line.match(/^dependencies:/)) { - inDependenciesSection = true; - - // Check if dependencies are on the same line (array syntax) - const arrayMatch = line.match(/\[(.*)\]/); - if (arrayMatch) { - const deps = arrayMatch[1] - .split(',') - .map(dep => dep.trim().replace(/['"]/g, '')) - .filter(dep => dep.length > 0); - dependencies.push(...deps); - inDependenciesSection = false; - } - continue; - } - - // If we're in dependencies section and hit a non-indented line that's not a list item, exit - if (inDependenciesSection && line.match(/^[^ ]/) && !line.match(/^[ \t]*-/)) { - inDependenciesSection = false; - } - - // Parse list format dependencies - if (inDependenciesSection && line.match(/^[ \t]*-/)) { - const dep = line.replace(/^[ \t]*-[ \t]*/, '').replace(/[ \t]*$/, '').replace(/['"]/g, ''); - if (dep.length > 0) { - dependencies.push(dep); - } - } - } - - return dependencies; -}; - -// Function to extract status from frontmatter -const _extractStatus = (frontmatter) => { - const lines = frontmatter.split('\n'); - - for (const line of lines) { - if (line.match(/^status:/)) { - return line.replace(/^status:[ \t]*/, '').replace(/^["']/, '').replace(/["']$/, '').trim(); - } - } - - return null; -}; - -// Main function -const _main = (startPath = process.cwd()) => { - // Check arguments - if (process.argv.length !== 4) { - _printError('Invalid number of arguments'); - console.log('Usage: node check-task-dependencies.cjs '); - console.log('Example: node check-task-dependencies.cjs 16 03'); - process.exit(1); - } - - const inputId = process.argv[2]; - const taskId = process.argv[3]; - - const resolved = resolvePlan(inputId, startPath); - - if (!resolved) { - _printError(`Plan "${inputId}" not found or invalid`); - process.exit(1); - } - - const { - planDir, - planId - } = resolved; - _printInfo(`Found plan directory: ${planDir}`); - - // Find task file - const taskFile = _findTaskFile(planDir, taskId); - - if (!taskFile || !fs.existsSync(taskFile)) { - _printError(`Task with ID ${taskId} not found in plan ${planId}`); - process.exit(1); - } - - _printInfo(`Checking task: ${path.basename(taskFile)}`); - console.log(''); - - // Read and parse task file - const taskContent = fs.readFileSync(taskFile, 'utf8'); - const frontmatter = parseFrontmatter(taskContent); - const dependencies = _extractDependencies(frontmatter); - - // Check if there are any dependencies - if (dependencies.length === 0) { - _printSuccess('Task has no dependencies - ready to execute!'); - process.exit(0); - } - - // Display dependencies - _printInfo('Task dependencies found:'); - dependencies.forEach(dep => { - console.log(` - Task ${dep}`); - }); - console.log(''); - - // Check each dependency - let allResolved = true; - let unresolvedDeps = []; - let resolvedCount = 0; - const totalDeps = dependencies.length; - - _printInfo('Checking dependency status...'); - console.log(''); - - for (const depId of dependencies) { - // Find dependency task file - const depFile = _findTaskFile(planDir, depId); - - if (!depFile || !fs.existsSync(depFile)) { - _printError(`Dependency task ${depId} not found`); - allResolved = false; - unresolvedDeps.push(`${depId} (not found)`); - continue; - } - - // Extract status from dependency task - const depContent = fs.readFileSync(depFile, 'utf8'); - const depFrontmatter = parseFrontmatter(depContent); - const status = _extractStatus(depFrontmatter); - - // Check if status is completed - if (status === 'completed') { - _printSuccess(`Task ${depId} - Status: completed ✓`); - resolvedCount++; - } else { - _printWarning(`Task ${depId} - Status: ${status || 'unknown'} ✗`); - allResolved = false; - unresolvedDeps.push(`${depId} (${status || 'unknown'})`); - } - } - - console.log(''); - _printInfo('========================================='); - _printInfo('Dependency Check Summary'); - _printInfo('========================================='); - _printInfo(`Total dependencies: ${totalDeps}`); - _printInfo(`Resolved: ${resolvedCount}`); - _printInfo(`Unresolved: ${totalDeps - resolvedCount}`); - console.log(''); - - if (allResolved) { - _printSuccess(`All dependencies are resolved! Task ${taskId} is ready to execute.`); - process.exit(0); - } else { - _printError(`Task ${taskId} has unresolved dependencies:`); - unresolvedDeps.forEach(dep => { - console.log(dep); - }); - _printInfo('Please complete the dependencies before executing this task.'); - process.exit(1); - } -}; - -// Run the script -if (require.main === module) { - _main(); -} - -module.exports = { - _main -}; diff --git a/.ai/task-manager/config/scripts/compose-prompt.cjs b/.ai/task-manager/config/scripts/compose-prompt.cjs deleted file mode 100755 index 99e3a60..0000000 --- a/.ai/task-manager/config/scripts/compose-prompt.cjs +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env node - -/** - * Runtime Prompt Composition Script - * - * Reads markdown command files, performs variable substitution, and outputs - * composed prompts to enable uninterrupted workflow execution. - * - * Usage: - * node compose-prompt.cjs --template "create-plan.md" --variable "ARGUMENTS=user input" --variable "1=51" - * - * Arguments: - * --template: Relative path to template file (e.g., "create-plan.md") - * --variable: Key=value pairs for substitution (can be specified multiple times) - * - * Output: - * Composed markdown prompt to stdout with variables substituted - * - * Exit Codes: - * 0: Success - * 1: Error (with message to stderr) - */ - -const fs = require('fs'); -const path = require('path'); - -/** - * Parse command line arguments - * @returns {Object} Parsed arguments with template and variables - */ -function parseArguments() { - const args = process.argv.slice(2); - const result = { - template: null, - variables: {} - }; - - for (let i = 0; i < args.length; i++) { - if (args[i] === '--template') { - if (i + 1 >= args.length) { - throw new Error('--template requires a value'); - } - result.template = args[++i]; - } else if (args[i] === '--variable') { - if (i + 1 >= args.length) { - throw new Error('--variable requires a value'); - } - const varArg = args[++i]; - const eqIndex = varArg.indexOf('='); - if (eqIndex === -1) { - throw new Error(`Invalid variable format: ${varArg}. Expected format: key=value`); - } - const key = varArg.substring(0, eqIndex); - const value = varArg.substring(eqIndex + 1); - result.variables[key] = value; - } else { - throw new Error(`Unknown argument: ${args[i]}`); - } - } - - if (!result.template) { - throw new Error('--template argument is required'); - } - - return result; -} - -/** - * Find the template file in the appropriate directory - * Priority: .claude/commands/tasks/ then templates/assistant/commands/tasks/ - * @param {string} templateName - Relative path to template file - * @returns {string} Absolute path to template file - */ -function findTemplateFile(templateName) { - // Get the root directory (assuming script is in templates/ai-task-manager/config/scripts/) - const scriptDir = __dirname; - const rootDir = path.resolve(scriptDir, '../../../..'); - - // Define search paths in priority order - const searchPaths = [ - path.join(rootDir, '.claude', 'commands', 'tasks', templateName), - path.join(rootDir, 'templates', 'assistant', 'commands', 'tasks', templateName) - ]; - - for (const searchPath of searchPaths) { - if (fs.existsSync(searchPath)) { - return searchPath; - } - } - - throw new Error(`Template not found: ${templateName}`); -} - -/** - * Parse YAML frontmatter from markdown content - * Based on the parseFrontmatter function from src/utils.ts - * @param {string} content - The markdown content with frontmatter - * @returns {Object} Object containing frontmatter and body content - */ -function parseFrontmatter(content) { - const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?$/; - const match = content.match(frontmatterRegex); - - if (!match) { - return { - frontmatter: {}, - body: content - }; - } - - const frontmatterContent = match[1] || ''; - const bodyContent = match[2] || ''; - - // Simple YAML parser for our specific use case - const frontmatter = {}; - const lines = frontmatterContent.split('\n'); - - for (const line of lines) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) continue; - - const colonIndex = trimmed.indexOf(':'); - if (colonIndex === -1) continue; - - const key = trimmed.substring(0, colonIndex).trim(); - const value = trimmed.substring(colonIndex + 1).trim(); - - // Remove quotes if present - frontmatter[key] = value.replace(/^["']|["']$/g, ''); - } - - return { - frontmatter, - body: bodyContent - }; -} - -/** - * Perform variable substitution in the template body - * Replaces $ARGUMENTS, $1, $2, etc. with provided values - * Does NOT process frontmatter variables (those stay as-is) - * @param {string} body - The template body content - * @param {Object} variables - Key-value pairs for substitution - * @returns {string} Body content with substitutions applied - */ -function substituteVariables(body, variables) { - let result = body; - - // Replace $ARGUMENTS if provided - if (variables.ARGUMENTS !== undefined) { - // Use regex with negative lookahead to avoid replacing $ARGUMENTS that are part of longer identifiers - result = result.replace(/\$ARGUMENTS(?![0-9A-Za-z_])/g, variables.ARGUMENTS); - } - - // Replace positional arguments ($1, $2, $3, etc.) - // Use regex with negative lookahead to avoid replacing $1 that's part of $10, etc. - for (const key in variables) { - if (/^\d+$/.test(key)) { - const pattern = new RegExp(`\\$${key}(?![0-9])`, 'g'); - result = result.replace(pattern, variables[key]); - } - } - - return result; -} - -/** - * Reconstruct markdown content with frontmatter - * @param {Object} frontmatter - The frontmatter object - * @param {string} body - The body content - * @returns {string} Complete markdown content - */ -function reconstructMarkdown(frontmatter, body) { - if (Object.keys(frontmatter).length === 0) { - return body; - } - - let result = '---\n'; - for (const [key, value] of Object.entries(frontmatter)) { - // Preserve original formatting - add quotes if value contains special characters - if (typeof value === 'string' && (value.includes(':') || value.includes('[') || value.includes(']'))) { - result += `${key}: "${value}"\n`; - } else { - result += `${key}: ${value}\n`; - } - } - result += '---\n'; - - if (body) { - result += body; - } - - return result; -} - -/** - * Main execution function - */ -function main() { - try { - // Parse command line arguments - const { template, variables } = parseArguments(); - - // Find the template file - const templatePath = findTemplateFile(template); - - // Read the template file - const content = fs.readFileSync(templatePath, 'utf-8'); - - // Parse frontmatter and body - const { frontmatter, body } = parseFrontmatter(content); - - // Perform variable substitution on the body only - const substitutedBody = substituteVariables(body, variables); - - // Reconstruct the markdown with frontmatter preserved - const output = reconstructMarkdown(frontmatter, substitutedBody); - - // Output to stdout - process.stdout.write(output); - - // Exit successfully - process.exit(0); - } catch (error) { - // Write error to stderr - process.stderr.write(`Error: ${error.message}\n`); - - // Exit with error code - process.exit(1); - } -} - -// Execute main function -main(); diff --git a/.ai/task-manager/config/scripts/create-feature-branch.cjs b/.ai/task-manager/config/scripts/create-feature-branch.cjs deleted file mode 100644 index d0debe2..0000000 --- a/.ai/task-manager/config/scripts/create-feature-branch.cjs +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/env node - -/** - * Script: create-feature-branch.cjs - * Purpose: Create a git feature branch for a plan execution - * Usage: node create-feature-branch.cjs - * - * Exit codes: - * 0 = Success (branch created, already exists, or not on main/master) - * 1 = Error (not git repo, uncommitted changes, plan not found) - */ - -const { execSync } = require('child_process'); -const fs = require('fs'); -const path = require('path'); -const { resolvePlan } = require('./shared-utils.cjs'); - -// Color functions for output -const _printError = (message) => { - console.error(`ERROR: ${message}`); -}; - -const _printSuccess = (message) => { - console.log(`✓ ${message}`); -}; - -const _printWarning = (message) => { - console.log(`⚠ ${message}`); -}; - -const _printInfo = (message) => { - console.log(message); -}; - -/** - * Execute a git command and return the output - * @param {string} command - Git command to execute - * @returns {string|null} Command output or null on error - */ -const _execGit = (command) => { - try { - return execSync(command, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim(); - } catch (_error) { - return null; - } -}; - -/** - * Check if current directory is inside a git repository - * @returns {boolean} - */ -const _isGitRepo = () => { - const result = _execGit('git rev-parse --is-inside-work-tree'); - return result === 'true'; -}; - -/** - * Get current git branch name - * @returns {string|null} - */ -const _getCurrentBranch = () => { - return _execGit('git rev-parse --abbrev-ref HEAD'); -}; - -/** - * Check if working tree has uncommitted changes - * @returns {boolean} - */ -const _hasUncommittedChanges = () => { - const status = _execGit('git status --porcelain'); - return status !== null && status.length > 0; -}; - -/** - * Check if a branch exists locally or remotely - * @param {string} branchName - Branch name to check - * @returns {boolean} - */ -const _branchExists = (branchName) => { - // Check local branches - const localBranches = _execGit('git branch --list'); - if (localBranches && localBranches.split('\n').some(b => b.trim().replace('* ', '') === branchName)) { - return true; - } - - // Check remote branches - const remoteBranches = _execGit('git branch -r --list'); - if (remoteBranches && remoteBranches.split('\n').some(b => b.trim().includes(branchName))) { - return true; - } - - return false; -}; - -/** - * Sanitize plan name for use in branch name - * @param {string} planName - Original plan name from directory - * @returns {string} Sanitized branch name segment - */ -const _sanitizeBranchName = (planName) => { - return planName - .toLowerCase() - .replace(/[^a-z0-9-]/g, '-') // Replace non-alphanumeric chars with hyphens - .replace(/-+/g, '-') // Collapse multiple hyphens - .replace(/^-|-$/g, '') // Remove leading/trailing hyphens - .substring(0, 60); // Max 60 chars -}; - -/** - * Extract plan name from plan directory - * @param {string} planDir - Full path to plan directory - * @returns {string} Plan name portion (e.g., "update-docs" from "58--update-docs") - */ -const _extractPlanName = (planDir) => { - const dirName = path.basename(planDir); - // Match pattern: {id}--{name} - const match = dirName.match(/^\d+--(.+)$/); - return match ? match[1] : dirName; -}; - -// Main function -const _main = (startPath = process.cwd()) => { - // Check arguments - if (process.argv.length < 3) { - _printError('Missing plan ID argument'); - console.log('Usage: node create-feature-branch.cjs '); - console.log('Example: node create-feature-branch.cjs 58'); - process.exit(1); - } - - const inputId = process.argv[2]; - - // Step 1: Check if this is a git repository - if (!_isGitRepo()) { - _printError('Not a git repository'); - process.exit(1); - } - - // Step 2: Resolve the plan - const resolved = resolvePlan(inputId, startPath); - - if (!resolved) { - _printError(`Plan "${inputId}" not found or invalid`); - process.exit(1); - } - - const { planDir, planId } = resolved; - _printInfo(`Found plan: ${path.basename(planDir)}`); - - // Step 3: Check current branch - const currentBranch = _getCurrentBranch(); - - if (!currentBranch) { - _printError('Could not determine current git branch'); - process.exit(1); - } - - if (currentBranch !== 'main' && currentBranch !== 'master') { - _printWarning(`Not on main/master branch (current: ${currentBranch})`); - _printInfo('Proceeding without creating a new branch'); - process.exit(0); - } - - // Step 4: Check for uncommitted changes - if (_hasUncommittedChanges()) { - _printError('Uncommitted changes detected in working tree'); - _printInfo('Please commit or stash your changes before creating a feature branch'); - process.exit(1); - } - - // Step 5: Build branch name - const planName = _extractPlanName(planDir); - const sanitizedName = _sanitizeBranchName(planName); - const branchName = `feature/${planId}--${sanitizedName}`; - - // Step 6: Check if branch already exists - if (_branchExists(branchName)) { - _printWarning(`Branch "${branchName}" already exists`); - _printInfo('Proceeding with existing branch'); - process.exit(0); - } - - // Step 7: Create and checkout the branch - const createResult = _execGit(`git checkout -b "${branchName}"`); - - if (createResult === null) { - _printError(`Failed to create branch "${branchName}"`); - process.exit(1); - } - - _printSuccess(`Created and switched to branch: ${branchName}`); - process.exit(0); -}; - -// Run the script -if (require.main === module) { - _main(); -} - -module.exports = { - _main, - _sanitizeBranchName, - _extractPlanName -}; diff --git a/.ai/task-manager/config/scripts/extract-task-skills.cjs b/.ai/task-manager/config/scripts/extract-task-skills.cjs deleted file mode 100644 index bd14431..0000000 --- a/.ai/task-manager/config/scripts/extract-task-skills.cjs +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env node - -/** - * Extract skills from a task file's YAML frontmatter. - * - * Usage: node extract-task-skills.cjs - * Output: One skill per line, trimmed, empty lines removed. - * - * Supports both inline array and block list formats: - * skills: [skill-a, skill-b] - * skills: - * - skill-a - * - "skill-b" - */ - -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -const taskFile = process.argv[2]; -if (!taskFile) { - console.error('Usage: node extract-task-skills.cjs '); - process.exit(1); -} - -const content = fs.readFileSync(path.resolve(taskFile), 'utf8'); -const lines = content.split('\n'); - -let inFrontmatter = false; -let frontmatterClosed = false; -let inSkills = false; -const skills = []; - -for (const line of lines) { - if (frontmatterClosed) break; - - if (line.trim() === '---') { - if (!inFrontmatter) { - inFrontmatter = true; - continue; - } - // Second delimiter – end of frontmatter - frontmatterClosed = true; - break; - } - - if (!inFrontmatter) continue; - - // Detect "skills:" key - if (/^skills\s*:/.test(line)) { - inSkills = true; - - // Check for inline array: skills: [a, b, c] - const inlineMatch = line.match(/\[(.*)]/); - if (inlineMatch) { - inlineMatch[1] - .split(',') - .map(s => s.trim().replace(/^["']|["']$/g, '')) - .filter(Boolean) - .forEach(s => skills.push(s)); - inSkills = false; - } - continue; - } - - if (inSkills) { - // A non-indented, non-empty line ends the block list - if (/^\S/.test(line)) { - inSkills = false; - continue; - } - // List item: " - skill-name" - const itemMatch = line.match(/^\s*-\s*(.*)/); - if (itemMatch) { - const value = itemMatch[1].trim().replace(/^["']|["']$/g, ''); - if (value) skills.push(value); - } - } -} - -if (skills.length > 0) { - console.log(skills.join('\n')); -} diff --git a/.ai/task-manager/config/scripts/find-root.cjs b/.ai/task-manager/config/scripts/find-root.cjs deleted file mode 100755 index cad560d..0000000 --- a/.ai/task-manager/config/scripts/find-root.cjs +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -const { findTaskManagerRoot } = require('./shared-utils.cjs'); - -try { - const root = findTaskManagerRoot(); - process.exit(root ? 0 : 1); -} catch (err) { - process.exit(1); -} diff --git a/.ai/task-manager/config/scripts/get-next-plan-id.cjs b/.ai/task-manager/config/scripts/get-next-plan-id.cjs deleted file mode 100644 index 9e69256..0000000 --- a/.ai/task-manager/config/scripts/get-next-plan-id.cjs +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const path = require('path'); -const { findTaskManagerRoot, getAllPlans } = require('./shared-utils.cjs'); - -/** - * Error logging utility - * @private - * @param {string} message - Error message - * @param {...any} args - Additional arguments to log - */ -function _errorLog(message, ...args) { - console.error(`[ERROR] ${message}`, ...args); -} - -/** - * Get the next available plan ID by scanning existing plan files - * @private - * @returns {number} Next available plan ID - */ -function _getNextPlanId() { - const taskManagerRoot = findTaskManagerRoot(); - - if (!taskManagerRoot) { - _errorLog('No .ai/task-manager/plans directory found in current directory or any parent directory.'); - _errorLog(''); - _errorLog('Please ensure you are in a project with task manager initialized, or navigate to the correct'); - _errorLog('project directory. The task manager looks for the .ai/task-manager/plans structure starting'); - _errorLog('from the current working directory and traversing upward through parent directories.'); - _errorLog(''); - _errorLog(`Current working directory: ${process.cwd()}`); - process.exit(1); - } - - const plans = getAllPlans(taskManagerRoot); - const maxId = plans.reduce((max, p) => Math.max(max, p.id), 0); - - return maxId + 1; -} - -// Output the next plan ID if run directly -if (require.main === module) { - console.log(_getNextPlanId()); -} - -module.exports = { - _getNextPlanId -}; diff --git a/.ai/task-manager/config/scripts/get-next-task-id.cjs b/.ai/task-manager/config/scripts/get-next-task-id.cjs deleted file mode 100644 index 0d5d76c..0000000 --- a/.ai/task-manager/config/scripts/get-next-task-id.cjs +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const path = require('path'); -const { - resolvePlan, - extractIdFromFrontmatter -} = require('./shared-utils.cjs'); - -/** - * Get the next available task ID for a specific plan - * @private - * @param {number|string} inputId - The plan ID or path to get next task ID for - * @returns {number} Next available task ID - */ -function _getNextTaskId(inputId) { - if (!inputId) { - console.error('Error: Plan ID or path is required'); - process.exit(1); - } - - const resolved = resolvePlan(inputId); - - if (!resolved) { - console.error(`Error: Plan "${inputId}" not found or invalid.`); - process.exit(1); - } - - const { - planDir - } = resolved; - const tasksPath = path.join(planDir, 'tasks'); - - // Optimization: If no tasks directory exists, return 1 immediately (90% case) - if (!fs.existsSync(tasksPath)) { - return 1; - } - - let maxId = 0; - - try { - const entries = fs.readdirSync(tasksPath, { - withFileTypes: true - }); - - // Another optimization: If directory is empty, return 1 immediately - if (entries.length === 0) { - return 1; - } - - entries.forEach(entry => { - if (entry.isFile() && entry.name.endsWith('.md')) { - try { - const filePath = path.join(tasksPath, entry.name); - const content = fs.readFileSync(filePath, 'utf8'); - const id = extractIdFromFrontmatter(content); - - if (id !== null && id > maxId) { - maxId = id; - } - } catch (err) { - // Skip corrupted files - } - } - }); - } catch (err) { - // Skip directories that can't be read - } - - return maxId + 1; -} - -// Get plan ID from command line argument -if (require.main === module) { - const inputId = process.argv[2]; - console.log(_getNextTaskId(inputId)); -} - -module.exports = { - _getNextTaskId -}; diff --git a/.ai/task-manager/config/scripts/shared-utils.cjs b/.ai/task-manager/config/scripts/shared-utils.cjs deleted file mode 100644 index c5da5f1..0000000 --- a/.ai/task-manager/config/scripts/shared-utils.cjs +++ /dev/null @@ -1,418 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const path = require('path'); - -/** - * Validate that a task manager root is correctly initialized - * @internal - * @param {string} taskManagerPath - Path to .ai/task-manager - * @returns {boolean} True if root is valid, false otherwise - */ -function isValidTaskManagerRoot(taskManagerPath) { - try { - if (!fs.existsSync(taskManagerPath)) return false; - if (!fs.lstatSync(taskManagerPath).isDirectory()) return false; - - // Must contain .init-metadata.json with valid version prop - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - if (!fs.existsSync(metadataPath)) return false; - - const metadataContent = fs.readFileSync(metadataPath, 'utf8'); - const metadata = JSON.parse(metadataContent); - - return metadata && typeof metadata === 'object' && 'version' in metadata; - } catch (err) { - return false; - } -} - -/** - * Check if a directory contains a valid task manager root - * @internal - * @param {string} directory - Directory to check - * @returns {string|null} Task manager path if valid, otherwise null - */ -function getTaskManagerAt(directory) { - const taskManagerPath = path.join(directory, '.ai', 'task-manager'); - return isValidTaskManagerRoot(taskManagerPath) ? taskManagerPath : null; -} - -/** - * Get all parent directories from a start path up to the filesystem root (recursive) - * @private - * @param {string} currentPath - Path to start from - * @param {string[]} [acc=[]] - Accumulator for paths - * @returns {string[]} Array of paths from start to root - */ -function _getParentPaths(currentPath, acc = []) { - const absolutePath = path.resolve(currentPath); - const nextAcc = [...acc, absolutePath]; - const parentPath = path.dirname(absolutePath); - - if (parentPath === absolutePath) { - return nextAcc; - } - - return _getParentPaths(parentPath, nextAcc); -} - -/** - * Find the task manager root directory by traversing up from an optional start path - * @param {string} [startPath=process.cwd()] - Starting path for root discovery (defaults to current working directory) - * @returns {string|null} Path to task manager root or null if not found - */ -function findTaskManagerRoot(startPath = process.cwd()) { - const paths = _getParentPaths(startPath); - const foundPath = paths.find(p => getTaskManagerAt(p)); - return foundPath ? getTaskManagerAt(foundPath) : null; -} - -/** - * Check if the path matches the standard .ai/task-manager structure - * @param {string} filePath - Path to plan file - * @returns {string|null} The possible root path if matches, otherwise null - */ -function checkStandardRootShortcut(filePath) { - const planDir = path.dirname(filePath); - const parentDir = path.dirname(planDir); - const possibleRoot = path.dirname(parentDir); - - const parentBase = path.basename(parentDir); - const isPlansOrArchive = parentBase === 'plans' || parentBase === 'archive'; - if (!isPlansOrArchive) return null; - - if (path.basename(possibleRoot) !== 'task-manager') return null; - - const dotAiDir = path.dirname(possibleRoot); - if (path.basename(dotAiDir) !== '.ai') return null; - - return isValidTaskManagerRoot(possibleRoot) ? possibleRoot : null; -} - -/** - * Parse YAML frontmatter for ID - * @param {string} content - File content - * @param {string} [filePath] - Optional file path for error context - * @returns {number|null} Extracted ID or null - */ -function extractIdFromFrontmatter(content, filePath = 'unknown') { - // Check for frontmatter block existence - const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/); - if (!frontmatterMatch) { - return null; - } - - const frontmatterText = frontmatterMatch[1]; - - // Enhanced patterns to handle various YAML formats: - // - id: 5 (simple numeric) - // - id: "5" (double quoted) - // - id: '5' (single quoted) - // - "id": 5 (quoted key) - // - 'id': 5 (single quoted key) - // - id : 5 (extra spaces) - // - id: 05 (zero-padded) - // - id: +5 (explicit positive) - // - Mixed quotes: 'id': "5" (different quote types) - const patterns = [ - // Most flexible pattern - handles quoted/unquoted keys and values with optional spaces - /^\s*["']?id["']?\s*:\s*["']?([+-]?\d+)["']?\s*(?:#.*)?$/mi, - // Simple numeric with optional whitespace and comments - /^\s*id\s*:\s*([+-]?\d+)\s*(?:#.*)?$/mi, - // Double quoted values - /^\s*["']?id["']?\s*:\s*"([+-]?\d+)"\s*(?:#.*)?$/mi, - // Single quoted values - /^\s*["']?id["']?\s*:\s*'([+-]?\d+)'\s*(?:#.*)?$/mi, - // Mixed quotes - quoted key, unquoted value - /^\s*["']id["']\s*:\s*([+-]?\d+)\s*(?:#.*)?$/mi, - // YAML-style with pipe or greater-than indicators (edge case) - /^\s*id\s*:\s*[|>]\s*([+-]?\d+)\s*$/mi - ]; - - // Try each pattern in order using functional find - const foundPattern = patterns - .map(regex => ({ regex, match: frontmatterText.match(regex) })) - .find(({ match }) => match); - - if (!foundPattern) return null; - - const { match, regex } = foundPattern; - const rawId = match[1]; - const id = parseInt(rawId, 10); - - // Validate the parsed ID - if (isNaN(id)) { - console.error(`[ERROR] Invalid ID value "${rawId}" in ${filePath} - not a valid number`); - return null; - } - - if (id < 0) { - console.error(`[ERROR] Invalid ID value ${id} in ${filePath} - ID must be non-negative`); - return null; - } - - if (id > Number.MAX_SAFE_INTEGER) { - console.error(`[ERROR] Invalid ID value ${id} in ${filePath} - ID exceeds maximum safe integer`); - return null; - } - - return id; -} - -/** - * Parse YAML frontmatter from markdown content - * Returns the frontmatter text as a string (not parsed as YAML) - * @param {string} content - The markdown content with frontmatter - * @returns {string} Frontmatter text or empty string if not found - */ -function parseFrontmatter(content) { - const lines = content.split('\n'); - - const result = lines.reduce((acc, line) => { - if (acc.done) return acc; - - if (line.trim() === '---') { - const nextDelimiterCount = acc.delimiterCount + 1; - if (nextDelimiterCount === 2) { - return { ...acc, delimiterCount: nextDelimiterCount, done: true }; - } - return { ...acc, delimiterCount: nextDelimiterCount }; - } - - if (acc.delimiterCount === 1) { - return { ...acc, frontmatterLines: [...acc.frontmatterLines, line] }; - } - - return acc; - }, { delimiterCount: 0, frontmatterLines: [], done: false }); - - return result.frontmatterLines.join('\n'); -} - -/** - * Find plan file and directory for a given plan ID - * @param {string|number} planId - Plan ID to search for - * @param {string} [taskManagerRoot] - Optional task manager root path (uses findTaskManagerRoot() if not provided) - * @returns {Object|null} Object with planFile and planDir, or null if not found - */ -function findPlanById(planId, taskManagerRoot) { - const numericPlanId = parseInt(planId, 10); - if (isNaN(numericPlanId)) return null; - - const plans = getAllPlans(taskManagerRoot); - const plan = plans.find(p => p.id === numericPlanId); - - if (!plan) return null; - - return { - planFile: plan.file, - planDir: plan.dir, - isArchive: plan.isArchive - }; -} - -/** - * Count task files in a plan's tasks directory - * @param {string} planDir - Plan directory path - * @returns {number} Number of task files found - */ -function countTasks(planDir) { - const tasksDir = path.join(planDir, 'tasks'); - - if (!fs.existsSync(tasksDir)) { - return 0; - } - - try { - const stats = fs.lstatSync(tasksDir); - if (!stats.isDirectory()) { - return 0; - } - - const files = fs.readdirSync(tasksDir).filter(f => f.endsWith('.md')); - return files.length; - } catch (err) { - return 0; - } -} - -/** - * Check if execution blueprint section exists in plan file - * @param {string} planFile - Path to plan file - * @returns {boolean} True if blueprint section exists, false otherwise - */ -function checkBlueprintExists(planFile) { - try { - const planContent = fs.readFileSync(planFile, 'utf8'); - const blueprintExists = /^## Execution Blueprint/m.test(planContent); - return blueprintExists; - } catch (err) { - return false; - } -} - -/** - * Validate plan file frontmatter - * @param {string} filePath - Path to plan file - * @returns {number|null} Plan ID from frontmatter or null if invalid - */ -function validatePlanFile(filePath) { - try { - if (!fs.existsSync(filePath)) { - return null; - } - - const content = fs.readFileSync(filePath, 'utf8'); - const frontmatter = parseFrontmatter(content); - - // Check for required fields - if (!frontmatter) { - return null; - } - - // Check for 'created' field - if (!/\bcreated\b/i.test(frontmatter)) { - return null; - } - - // Extract and return ID - const id = extractIdFromFrontmatter(content, filePath); - return id; - } catch (err) { - return null; - } -} - -/** - * Get all plans (active and archived) in a task manager root - * @param {string} [taskManagerRoot] - Task manager root path - * @returns {Array} Array of plan objects { id, file, dir, isArchive } - */ -function getAllPlans(taskManagerRoot) { - const root = taskManagerRoot || findTaskManagerRoot(); - if (!root) return []; - - const types = [ - { dir: path.join(root, 'plans'), isArchive: false }, - { dir: path.join(root, 'archive'), isArchive: true } - ]; - - return types.flatMap(({ dir, isArchive }) => { - if (!fs.existsSync(dir)) return []; - - try { - const entries = fs.readdirSync(dir, { withFileTypes: true }); - return entries.flatMap(entry => { - if (!entry.isDirectory()) return []; - - const planDirPath = path.join(dir, entry.name); - - try { - const planDirEntries = fs.readdirSync(planDirPath, { withFileTypes: true }); - return planDirEntries - .filter(planEntry => planEntry.isFile() && planEntry.name.endsWith('.md')) - .flatMap(planEntry => { - const filePath = path.join(planDirPath, planEntry.name); - try { - const content = fs.readFileSync(filePath, 'utf8'); - const id = extractIdFromFrontmatter(content, filePath); - - if (id !== null) { - return { - id, - file: filePath, - dir: planDirPath, - isArchive, - name: entry.name - }; - } - } catch (err) { - // Skip files that can't be read - } - return []; - }); - } catch (err) { - return []; - } - }); - } catch (err) { - return []; - } - }); -} - -/** - * Resolve plan information from either a numeric ID or an absolute path - * @param {string|number} input - Numeric ID or absolute path - * @param {string} [startPath=process.cwd()] - Starting path for hierarchical search - * @returns {Object|null} { planFile, planDir, taskManagerRoot, planId } or null if not found - */ -function resolvePlan(input, startPath = process.cwd()) { - if (!input) return null; - const inputStr = String(input); - - // 1. Handle Absolute Path - if (inputStr.startsWith('/')) { - const planId = validatePlanFile(inputStr); - if (planId === null) return null; - - const tmRoot = checkStandardRootShortcut(inputStr) || findTaskManagerRoot(path.dirname(inputStr)); - if (!tmRoot) return null; - - return { - planFile: inputStr, - planDir: path.dirname(inputStr), - taskManagerRoot: tmRoot, - planId - }; - } - - // 2. Handle Numeric ID with Hierarchical Search - const planId = parseInt(inputStr, 10); - if (isNaN(planId)) return null; - - const findInAncestry = (currentPath, searched = new Set()) => { - const tmRoot = findTaskManagerRoot(currentPath); - if (!tmRoot) return null; - - const normalized = path.normalize(tmRoot); - if (searched.has(normalized)) { - return null; - } - searched.add(normalized); - - const plan = findPlanById(planId, tmRoot); - if (plan) { - return { - planFile: plan.planFile, - planDir: plan.planDir, - taskManagerRoot: tmRoot, - planId - }; - } - - // Move to parent directory (parent of the directory containing task-manager) - const parentOfRoot = path.dirname(path.dirname(tmRoot)); - if (parentOfRoot === tmRoot) return null; - return findInAncestry(parentOfRoot, searched); - }; - - return findInAncestry(startPath); -} - -module.exports = { - findTaskManagerRoot, - isValidTaskManagerRoot, - getTaskManagerAt, - checkStandardRootShortcut, - validatePlanFile, - extractIdFromFrontmatter, - parseFrontmatter, - findPlanById, - countTasks, - checkBlueprintExists, - getAllPlans, - _getParentPaths, - resolvePlan -}; diff --git a/.ai/task-manager/config/scripts/validate-plan-blueprint.cjs b/.ai/task-manager/config/scripts/validate-plan-blueprint.cjs deleted file mode 100755 index cd12957..0000000 --- a/.ai/task-manager/config/scripts/validate-plan-blueprint.cjs +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); -const path = require('path'); -const sharedUtils = require('./shared-utils.cjs'); -const { - findTaskManagerRoot, - findPlanById, - countTasks, - checkBlueprintExists, - getAllPlans, - validatePlanFile, - checkStandardRootShortcut, - resolvePlan -} = sharedUtils; - -/** - * Error logging utility - * @private - * @param {string} message - Error message - * @param {...any} args - Additional arguments to log - */ -function _errorLog(message, ...args) { - console.error(`[ERROR] ${message}`, ...args); -} - -/** - * List available plans for error messaging - * @private - * @param {string} [taskManagerRoot] - Optional task manager root path - * @returns {string[]} Array of plan directory names - */ -function _listAvailablePlans(taskManagerRoot) { - const plans = getAllPlans(taskManagerRoot); - return plans - .map(p => p.name) - .sort((a, b) => { - const aIdMatch = a.match(/^(\d+)--/); - const bIdMatch = b.match(/^(\d+)--/); - if (!aIdMatch || !bIdMatch) return 0; - return parseInt(aIdMatch[1], 10) - parseInt(bIdMatch[1], 10); - }); -} - -/** - * Validate plan blueprint and output JSON or specific field - * @private - * @param {string|number} inputId - Plan ID or absolute path to validate - * @param {string} [fieldName] - Optional field name to extract (planFile, planDir, taskCount, blueprintExists, taskManagerRoot, planId) - * @param {string} [startPath] - Optional start path for finding task manager root - */ -function _validatePlanBlueprint(inputId, fieldName, startPath = process.cwd()) { - if (!inputId) { - _errorLog('Plan ID or absolute path is required'); - _errorLog(''); - _errorLog('Usage: node validate-plan-blueprint.cjs [field-name]'); - _errorLog(''); - _errorLog('Examples:'); - _errorLog(' node validate-plan-blueprint.cjs 47 # Output full JSON'); - _errorLog(' node validate-plan-blueprint.cjs /path/to/plan.md # Output full JSON for specific file'); - _errorLog(' node validate-plan-blueprint.cjs 47 planFile # Output just the plan file path'); - _errorLog(' node validate-plan-blueprint.cjs 47 blueprintExists # Output yes/no'); - process.exit(1); - } - - // Check if input is numeric (allowing padded zeros) - if not a number or path, it's invalid - const numericInput = parseInt(inputId, 10); - const isNumeric = !isNaN(numericInput); - const isAbsolutePath = inputId.startsWith('/'); - - if (!isNumeric && !isAbsolutePath) { - _errorLog(`Invalid plan ID: "${inputId}" is not a valid number`); - process.exit(1); - } - - const resolved = resolvePlan(inputId, startPath); - - if (!resolved) { - _errorLog(`Plan ID ${inputId} not found or invalid`); - _errorLog(''); - - const tmRoot = findTaskManagerRoot(startPath); - const availablePlans = _listAvailablePlans(tmRoot); - if (availablePlans.length > 0) { - _errorLog('Available plans:'); - availablePlans.forEach(plan => { - _errorLog(` ${plan}`); - }); - } - - process.exit(1); - } - - const { - planFile, - planDir, - taskManagerRoot, - planId - } = resolved; - - const taskCount = countTasks(planDir); - const blueprintExists = checkBlueprintExists(planFile); - - const result = { - planFile, - planDir, - taskManagerRoot, - planId, - taskCount, - blueprintExists: blueprintExists ? 'yes' : 'no' - }; - - // If field name is provided, output just that field - if (fieldName) { - const validFields = ['planFile', 'planDir', 'taskCount', 'blueprintExists', 'taskManagerRoot', 'planId']; - if (!validFields.includes(fieldName)) { - _errorLog(`Invalid field name: ${fieldName}`); - _errorLog(`Valid fields: ${validFields.join(', ')}`); - process.exit(1); - } - // Use process.stdout.write to avoid util.inspect colorization - process.stdout.write(String(result[fieldName]) + '\n'); - } else { - // Output full JSON - console.log(JSON.stringify(result, null, 2)); - } -} - -// Main execution -if (require.main === module) { - const planId = process.argv[2]; - const fieldName = process.argv[3]; - _validatePlanBlueprint(planId, fieldName); -} - -module.exports = { - _validatePlanBlueprint -}; diff --git a/.claude/agents/plan-creator.md b/.claude/agents/plan-creator.md index 427b37a..d7fae05 100644 --- a/.claude/agents/plan-creator.md +++ b/.claude/agents/plan-creator.md @@ -18,7 +18,7 @@ Create strategic blueprints that define WHAT to build and WHY, not HOW. Your pla ## Critical Workflow **1. Context Gathering** -- Read CLAUDE.md, README.md, package.json +- Read project instructions (AGENTS.md, README.md, or equivalent) - Search codebase for similar patterns - Ask specific, categorized clarification questions when gaps exist - STOP and wait for answers before planning @@ -73,8 +73,8 @@ Eliminate these anti-patterns: 1. Execute PRE_PLAN.md hook if exists 2. Analyze user input and search codebase 3. Ask clarification questions if needed (STOP until answered) -4. Generate Plan ID: `node .ai/task-manager/config/scripts/get-next-plan-id.cjs` -5. Create plan at `.ai/task-manager/plans/[ID]--[name]/plan-[ID]--[name].md` +4. Generate Plan ID: scan `.ai/strikethroo/plans/` and `.ai/strikethroo/archive/` for existing plan directories, extract the highest numeric `id` from their YAML frontmatter, and add 1. If no plans exist, use ID 1. +5. Create plan at `.ai/strikethroo/plans/[ID]--[name]/plan-[ID]--[name].md` 6. Execute POST_PLAN.md hook if exists 7. Output: ``` diff --git a/.claude/commands/tasks/create-plan-auto.md b/.claude/commands/tasks/create-plan-auto.md deleted file mode 100644 index ad57848..0000000 --- a/.claude/commands/tasks/create-plan-auto.md +++ /dev/null @@ -1,174 +0,0 @@ - ---- -argument-hint: "[userPrompt]" -description: Create a comprehensive plan without user interaction, resolving ambiguities autonomously. ---- -# Comprehensive Plan Creation (Autonomous Mode) - -You are a strategic planning specialist who creates actionable plan documents that balance comprehensive context with -disciplined scope control. Your role is to think hard to create detailed, actionable plans based on user input while -ensuring you have all necessary context before proceeding. Use the plan-creator sub-agent for this if it is available. - -**AUTONOMOUS MODE**: This command runs without user interaction. You must resolve all ambiguities by inspecting the -codebase, documentation, and project context. Do NOT ask the user any questions or wait for user input at any point. - ---- - -Use tools for the planning. You are encouraged to write your own specialized tools to research, analyze, and debug -any work order from the user. You are not restricted to the stack of the current project to create your own -specialized tools. - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -## Instructions - -Include $root/.ai/task-manager/config/TASK_MANAGER.md for the directory structure of tasks. - -The user input is: - - -$ARGUMENTS - - -If no user input is provided stop immediately and show an error message to the user. - -### Process Checklist - -Use your internal Todo task tool to track the following plan generation: - -- [ ] Read and execute $root/.ai/task-manager/config/hooks/PRE_PLAN.md -- [ ] User input and context analysis -- [ ] Autonomous clarification (resolve gaps via codebase inspection) -- [ ] Plan generation -- [ ] Read and execute $root/.ai/task-manager/config/hooks/POST_PLAN.md - -#### Step 1: Context Analysis -Before creating any plan, analyze the user's request for: -- **Objective**: What is the end goal? -- **Scope**: What are the boundaries and constraints? -- **Resources**: What tools, libraries, or infrastructure are available? -- **Success Criteria**: How will success be measured? -- **Dependencies**: What prerequisites or blockers exist? -- **Technical Requirements**: What technologies or skills are needed? - -#### Step 2: Autonomous Clarification Phase -If any critical context is missing: -1. Identify specific gaps in the information provided -2. Attempt to resolve each gap by inspecting the codebase, documentation, README files, assistant documents (CLAUDE.md, GEMINI.md, AGENTS.md), configuration files, and any other available project context -3. For gaps that cannot be resolved through codebase inspection, document your best-effort assumptions in the Plan Clarifications table with clear rationale -4. Record all assumptions prominently so they can be reviewed later - -CRITICAL: Do NOT ask the user any questions. Do NOT wait for user input. You must resolve all ambiguity autonomously through codebase analysis and reasonable assumptions. If you cannot determine something, state your assumption and proceed. - -#### Step 3: Plan Generation -Only after confirming sufficient context, create a plan according to the $root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md - -##### CRITICAL: Output Format - -Remember that a plan needs to be reviewed by a human. Be concise and to the point. Also, include mermaid diagrams to illustrate the plan. - -**Output Behavior: CRITICAL - Structured Output for Command Coordination** - -Always end your output with a standardized summary in this exact format, for command coordination: - -``` ---- - -Plan Summary: -- Plan ID: [numeric-id] -- Plan File: [full-path-to-plan-file] -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -###### Patterns to Avoid -Do not include the following in your plan output. -- Avoid time estimations -- Avoid task lists and mentions of phases (those are things we'll introduce later) -- Avoid code examples - -###### Frontmatter Structure - -Example: -```yaml ---- -id: 1 -summary: "Implement a comprehensive CI/CD pipeline using GitHub Actions for automated linting, testing, semantic versioning, and NPM publishing" -created: 2025-09-01 ---- -``` - -The schema for this frontmatter is: -```json -{ - "type": "object", - "required": ["id", "summary", "created"], - "properties": { - "id": { - "type": ["number"], - "description": "Unique identifier for the task. An integer." - }, - "summary": { - "type": "string", - "description": "A summary of the plan" - }, - "created": { - "type": "string", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "description": "Creation date in YYYY-MM-DD format" - } - }, - "additionalProperties": false -} -``` - -### Plan ID Generation - -Execute this script to determine the plan ID: - -```bash -next_id=$(node $root/config/scripts/get-next-plan-id.cjs) -``` - -**Key formatting:** -- **Front-matter**: Use numeric values (`id: 7`) -- **Directory names**: Use zero-padded strings (`07--plan-name`) diff --git a/.claude/commands/tasks/create-plan.md b/.claude/commands/tasks/create-plan.md deleted file mode 100644 index 1339dc6..0000000 --- a/.claude/commands/tasks/create-plan.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -argument-hint: "[userPrompt]" -description: Create a comprehensive plan to accomplish the request from the user. ---- -# Comprehensive Plan Creation - -You are a strategic planning specialist who creates actionable plan documents that balance comprehensive context with -disciplined scope control. Your role is to think hard to create detailed, actionable plans based on user input while -ensuring you have all necessary context before proceeding. Use the plan-creator sub-agent for this if it is available. - ---- - -Use tools for the planning. You are encouraged to write your own specialized tools to research, analyze, and debug -any work order from the user. You are not restricted to the stack of the current project to create your own -specialized tools. - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -## Instructions - -Include $root/.ai/task-manager/config/TASK_MANAGER.md for the directory structure of tasks. - -The user input is: - - -$ARGUMENTS - - -If no user input is provided stop immediately and show an error message to the user. - -### Process Checklist - -Use your internal Todo task tool to track the following plan generation: - -- [ ] Read and execute $root/.ai/task-manager/config/hooks/PRE_PLAN.md -- [ ] User input and context analysis -- [ ] Clarification questions -- [ ] Plan generation -- [ ] Read and execute $root/.ai/task-manager/config/hooks/POST_PLAN.md - -#### Step 1: Context Analysis -Before creating any plan, analyze the user's request for: -- **Objective**: What is the end goal? -- **Scope**: What are the boundaries and constraints? -- **Resources**: What tools, libraries, or infrastructure are available? -- **Success Criteria**: How will success be measured? -- **Dependencies**: What prerequisites or blockers exist? -- **Technical Requirements**: What technologies or skills are needed? - -#### Step 2: Clarification Phase -If any critical context is missing: -1. Identify specific gaps in the information provided -2. Ask targeted follow-up questions -3. Frame questions clearly with examples when helpful -4. Be extra cautious. Users miss important context very often. Don't hesitate to ask for additional clarifications. - -Try to answer your own questions first by inspecting the codebase, docs, and assistant documents like CLAUDE.md, GEMINI.md, AGENTS.md ... - -IMPORTANT: Once you have the user's answers go back to Step 2. Do this in a loop until you have no more questions. Ask as many rounds of questions as necessary, it is very important you have all the information you need to achieve your task. - -#### Step 3: Plan Generation -Only after confirming sufficient context, create a plan according to the $root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md - -##### CRITICAL: Output Format - -Remember that a plan needs to be reviewed by a human. Be concise and to the point. Also, include mermaid diagrams to illustrate the plan. - -**Output Behavior: CRITICAL - Structured Output for Command Coordination** - -Always end your output with a standardized summary in this exact format, for command coordination: - -``` ---- - -Plan Summary: -- Plan ID: [numeric-id] -- Plan File: [full-path-to-plan-file] -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -###### Patterns to Avoid -Do not include the following in your plan output. -- Avoid time estimations -- Avoid task lists and mentions of phases (those are things we'll introduce later) -- Avoid code examples - -###### Frontmatter Structure - -Example: -```yaml ---- -id: 1 -summary: "Implement a comprehensive CI/CD pipeline using GitHub Actions for automated linting, testing, semantic versioning, and NPM publishing" -created: 2025-09-01 ---- -``` - -The schema for this frontmatter is: -```json -{ - "type": "object", - "required": ["id", "summary", "created"], - "properties": { - "id": { - "type": ["number"], - "description": "Unique identifier for the task. An integer." - }, - "summary": { - "type": "string", - "description": "A summary of the plan" - }, - "created": { - "type": "string", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "description": "Creation date in YYYY-MM-DD format" - } - }, - "additionalProperties": false -} -``` - -### Plan ID Generation - -Execute this script to determine the plan ID: - -```bash -next_id=$(node $root/config/scripts/get-next-plan-id.cjs) -``` - -**Key formatting:** -- **Front-matter**: Use numeric values (`id: 7`) -- **Directory names**: Use zero-padded strings (`07--plan-name`) diff --git a/.claude/commands/tasks/execute-blueprint.md b/.claude/commands/tasks/execute-blueprint.md deleted file mode 100644 index 96d0528..0000000 --- a/.claude/commands/tasks/execute-blueprint.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -argument-hint: "[planId]" -description: Execute the task in the plan. ---- -# Task Execution - ---- - -You are the coordinator responsible for executing all tasks defined in the execution blueprint of a plan document, so choose an appropriate sub-agent for this role. Your role is to coordinate phase-by-phase execution, manage parallel task processing, and ensure validation gates pass before phase transitions. - -## Critical Rules - -1. **Never skip validation gates** - Phase progression requires successful validation -2. **Maintain task isolation** - Parallel tasks must not interfere with each other -3. **Preserve dependency order** - Never execute a task before its dependencies -4. **Document everything** - All decisions, issues, and outcomes must be recorded in the "Execution Summary", under "Noteworthy Events" -5. **Fail safely** - Better to halt and request help than corrupt the execution state - -## Input Requirements -- A plan document with an execution blueprint section. See /TASK_MANAGER.md to find the plan with ID $1 -- Task files with frontmatter metadata (id, group, dependencies, status) -- Validation gates document: `/config/hooks/POST_PHASE.md` - -### Input Error Handling - -If the plan does not exist, stop immediately and show an error to the user. - -**Note**: If tasks or the execution blueprint section are missing, they will be automatically generated before execution begins (see Task and Blueprint Validation below). - -### Task and Blueprint Validation - -Before proceeding with execution, validate that tasks exist and the execution blueprint has been generated. If either is missing, automatically invoke task generation. - -**Validation Steps:** - -First, discover the task manager root directory: - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -Then extract validation results: - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile) -plan_dir=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planDir) -task_count=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 taskCount) -blueprint_exists=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 blueprintExists) -``` - -4. **Automatic task generation**: - -If either `$task_count` is 0 or `$blueprint_exists` is "no": - - Display notification to user: "⚠️ Tasks or execution blueprint not found. Generating tasks automatically..." - - Execute the embedded task generation process below - - ## Embedded Task Generation - - Follow ALL instructions from `.*/**/generate-tasks.md` exactly for plan ID $1. It is important that you find and read the `generate-tasks.md` command first. - - This includes: - - Reading and processing the plan document - - Applying task minimization principles (20-30% reduction target) - - Creating atomic tasks with 1-2 skills each - - Generating proper task files with frontmatter and body structure - - Running all validation checklists - - Executing the POST_TASK_GENERATION_ALL hook - - ## Resume Blueprint Execution - - After task generation completes, continue with execution below. - -Otherwise, if tasks exist, proceed directly to execution. - -## Execution Process - -Use your internal Todo task tool to track the execution of all phases, and the final update of the plan with the summary. Example: - -- [ ] Create feature branch via `node $root/config/scripts/create-feature-branch.cjs $1` -- [ ] Validate or auto-generate tasks and execution blueprint if missing. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 1. -- [ ] Phase 1: Execute 1 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 1. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 2. -- [ ] Phase 2: Execute 3 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 2. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 3. -- [ ] Phase 3: Execute 1 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 3. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_EXECUTION.md hook after all phases complete. -- [ ] Update the Plan 7 with execution summary using $root/.ai/task-manager/config/hooks/EXECUTION_SUMMARY_TEMPLATE.md. -- [ ] Archive Plan 7. - -### Phase Pre-Execution - -Read and execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md - -### Phase Execution Workflow - -1. **Phase Initialization** - - Identify current phase from the execution blueprint - - List all tasks scheduled for parallel execution in this phase - -2. **Agent Selection and Task Assignment** -Read and execute $root/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md - -3. **Parallel Execution** - - Deploy all selected agents simultaneously using your internal Task tool - - Monitor execution progress for each task - - Capture outputs and artifacts from each agent - - Update task status in real-time - -4. **Phase Completion Verification** - - Ensure all tasks in the phase have status: "completed" - - Collect and review all task outputs - - Document any issues or exceptions encountered - -### Phase Post-Execution - -Read and execute $root/.ai/task-manager/config/hooks/POST_PHASE.md - - -### Phase Transition - - - Update phase status to "completed" in the Blueprint section of the plan $1 document. - - Initialize next phase - - Repeat process until all phases are complete - -### Error Handling - -#### Validation Gate Failures -Read and execute $root/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md - -### Output Requirements - -**Output Behavior:** - -Provide a concise execution summary: -- Example: "Execution completed. Review summary: `$root/.ai/task-manager/archive/[plan]/plan-[id].md`" - -**CRITICAL - Structured Output for Command Coordination:** - -Always end your output with a standardized summary in this exact format: - -``` ---- -Execution Summary: -- Plan ID: [numeric-id] -- Status: Archived -- Location: $root/.ai/task-manager/archive/[plan-id]--[plan-name]/ -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -## Optimization Guidelines - -- **Maximize parallelism**: Always run all available tasks in a phase simultaneously -- **Resource awareness**: Balance agent allocation with system capabilities -- **Early failure detection**: Monitor tasks actively to catch issues quickly -- **Continuous improvement**: Note patterns for future blueprint optimization - -## Post-Execution Processing - -Upon successful completion of all phases and validation gates, perform the following additional steps: - -- [ ] Post-Execution Validation -- [ ] Execution Summary Generation -- [ ] Plan Archival - -### 0. Post-Execution Validation - -Read and execute $root/.ai/task-manager/config/hooks/POST_EXECUTION.md - -If validation fails, halt execution. The plan remains in `plans/` for debugging. - -### 1. Execution Summary Generation - -Append an execution summary section to the plan document with the format described in $root/.ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md - -### 2. Plan Archival - -After successfully appending the execution summary: - -**Move completed plan to archive**: -```bash -mv $root/.ai/task-manager/plans/[plan-folder] $root/.ai/task-manager/archive/ -``` - -### Important Notes - -- **Only archive on complete success**: Archive operations should only occur when ALL phases are completed and ALL validation gates have passed -- **Failed executions remain active**: Plans that fail execution or validation should remain in the `plans/` directory for debugging and potential re-execution -- **Error handling**: If archival fails, log the error but do not fail the overall execution - the implementation work is complete -- **Preserve structure**: The entire plan folder (including all tasks and subdirectories) should be moved as-is to maintain referential integrity diff --git a/.claude/commands/tasks/execute-task.md b/.claude/commands/tasks/execute-task.md deleted file mode 100644 index ecb81a6..0000000 --- a/.claude/commands/tasks/execute-task.md +++ /dev/null @@ -1,348 +0,0 @@ ---- -argument-hint: "[planId] [taskId]" -description: Execute a single task with dependency validation and status management. ---- -# Single Task Execution - -You are responsible for executing a single task within a plan while maintaining strict dependency validation and proper status management. Your role is to ensure the task is ready for execution, deploy the appropriate agent, and track execution progress. - ---- - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -Use your internal Todo task tool to track the execution of all parts of the task. Example: - -- [ ] Validate task: file, status (including needs-clarification), and dependencies. -- [ ] Set task status to in-progress. -- [ ] Execute the task. -- [ ] Update task status to completed or failed. -- [ ] Document noteworthy events (if any). -- [ ] Emit structured output for orchestrator. - -## Critical Rules - -1. **Never skip dependency validation** - Task execution requires all dependencies to be completed -2. **Validate task status** - Never execute tasks that are already completed, in-progress, or needs-clarification -3. **Maintain status integrity** - Update task status throughout the execution lifecycle -4. **Document execution** - Record all outcomes and issues encountered -5. **Provide structured output** - Always emit the structured result block for orchestrator parsing - -## Input Requirements -- Plan ID: $1 (required) -- Task ID: $2 (required) -- Task management directory structure: `/` -- Dependency checking script: `$root/.ai/task-manager/config/scripts/check-task-dependencies.cjs` - -### Input Validation - -First, validate that both arguments are provided: - -```bash -if [ -z "$1" ] || [ -z "$2" ]; then - echo "Error: Both plan ID and task ID are required" - echo "Usage: /tasks:execute-task [planId] [taskId]" - echo "Example: /tasks:execute-task 16 03" - exit 1 -fi -``` - -## Execution Process - -### 1. Plan Location - -Locate the plan directory using the discovered root: - -```bash -plan_id="$1" -task_id="$2" - -# Find plan directory -plan_dir=$(find $root/{plans,archive} -type d -name "${plan_id}--*" 2>/dev/null | head -1) - -if [ -z "$plan_dir" ]; then - echo "Error: Plan with ID ${plan_id} not found" - echo "Available plans:" - find $root/plans -name "*--*" -type d | head -5 - exit 1 -fi - -echo "Found plan: $plan_dir" -``` - -### 2. Task File Validation - -Locate and validate the specific task file: - -```bash -# Handle both padded (01, 02) and unpadded (1, 2) task IDs -task_file="" -if [ -f "${plan_dir}/tasks/${task_id}--"*.md ]; then - task_file=$(ls "${plan_dir}/tasks/${task_id}--"*.md 2>/dev/null | head -1) -elif [ -f "${plan_dir}/tasks/0${task_id}--"*.md ]; then - task_file=$(ls "${plan_dir}/tasks/0${task_id}--"*.md 2>/dev/null | head -1) -fi - -if [ -z "$task_file" ] || [ ! -f "$task_file" ]; then - echo "Error: Task with ID ${task_id} not found in plan ${plan_id}" - echo "Available tasks in plan:" - find "$plan_dir/tasks" -name "*.md" -type f | head -5 - exit 1 -fi - -echo "Found task: $(basename "$task_file")" -``` - -### 3. Task Status Validation - -Check current task status to ensure it can be executed: - -```bash -# Extract current status from task frontmatter -current_status=$(awk ' - /^---$/ { if (++delim == 2) exit } - /^status:/ { - gsub(/^status:[ \t]*/, "") - gsub(/^["'\'']/, "") - gsub(/["'\'']$/, "") - print - exit - } -' "$task_file") - -echo "Current task status: ${current_status:-unknown}" - -# Validate status allows execution -case "$current_status" in - "completed") - echo "Error: Task ${task_id} is already completed" - echo "Use execute-blueprint to re-execute the entire plan if needed" - exit 1 - ;; - "in-progress") - echo "Error: Task ${task_id} is already in progress" - echo "Wait for current execution to complete or check for stale processes" - exit 1 - ;; - "needs-clarification") - echo "Error: Task ${task_id} is marked as 'needs-clarification'" - echo "Resolve clarification questions in the task file before execution" - exit 1 - ;; - "pending"|"failed"|"") - echo "Task status allows execution - proceeding..." - ;; - *) - echo "Warning: Unknown task status '${current_status}' - proceeding with caution..." - ;; -esac -``` - -#### Valid Status Transitions - -Reference for orchestrators and execution flow: - -- `pending` → `in-progress` (execution starts) -- `in-progress` → `completed` (successful execution) -- `in-progress` → `failed` (execution error) -- `failed` → `in-progress` (retry attempt) -- `pending` → `needs-clarification` (set externally by orchestrator or reviewer) -- `needs-clarification` → `pending` (clarification resolved, set externally) - -### 4. Dependency Validation - -Use the dependency checking script to validate all dependencies: - -```bash -# Call the dependency checking script -if ! node $root/config/scripts/check-task-dependencies.cjs "$plan_id" "$task_id"; then - echo "" - echo "Task execution blocked by unresolved dependencies." - echo "Please complete the required dependencies first." - exit 1 -fi - -echo "" -echo "✓ All dependencies resolved - proceeding with execution" -``` - -### 5. Agent Selection - -Read task skills and select appropriate task-specific agent: - -Read and execute $root/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md - -### 6. Status Update to In-Progress - -Update task status before execution: - -```bash -echo "Updating task status to in-progress..." - -# Create temporary file with updated status -temp_file=$(mktemp) -awk ' - /^---$/ { - if (++delim == 1) { - print - next - } else if (delim == 2) { - print "status: \"in-progress\"" - print - next - } - } - /^status:/ && delim == 1 { - print "status: \"in-progress\"" - next - } - { print } -' "$task_file" > "$temp_file" - -# Replace original file -mv "$temp_file" "$task_file" - -echo "✓ Task status updated to in-progress" -``` - -### 7. Task Execution - -Deploy the task using the Task tool with full context: - -**Task Deployment**: Use your internal Task tool to execute the task with the following context: -- Task file path: `$task_file` -- Plan directory: `$plan_dir` -- Required skills: `$task_skills` -- Agent selection: Based on skills analysis or general-purpose agent - -Read the complete task file and execute according to its requirements. The task includes: -- Objective and acceptance criteria -- Technical requirements and implementation notes -- Input dependencies and expected output artifacts - -### 8. Post-Execution Status Management - -After task completion, update the status based on execution outcome: - -```bash -temp_file=$(mktemp) -awk ' - /^---$/ { - if (++delim == 1) { - print - next - } else if (delim == 2) { - print "status: \"completed\"" - print - next - } - } - /^status:/ && delim == 1 { - print "status: \"completed\"" - next - } - { print } -' "$task_file" > "$temp_file" - -mv "$temp_file" "$task_file" - -echo "✓ Task ${task_id} status updated to completed" -``` - -### 9. Noteworthy Events Documentation - -After task execution (whether successful or failed), append a "Noteworthy Events" section to the task file body if anything noteworthy occurred during execution. - -Append to the end of the task file: - -```markdown -## Noteworthy Events -- [YYYY-MM-DD] [Event description with sufficient context for the orchestrator] -``` - -If no noteworthy events occurred, do not add the section. - -## Error Handling - -Read and execute $root/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md - -On any error, ensure you still emit the structured output block (see Output Requirements) with `Exit Code: 1`. - -## Output Requirements - -**CRITICAL - Structured Output for Orchestrator Coordination:** - -Always end your output with a standardized summary in this exact format: - -``` ---- -Task Execution Result: -- Plan ID: [plan-id] -- Task ID: [task-id] -- Exit Code: [0 for success, 1 for failure] -``` - -This structured output enables automated orchestration pipelines to parse results and determine next steps. It MUST be included regardless of success or failure. - -## Usage Examples - -```bash -# Execute a specific task -/tasks:execute-task 16 1 - -# Execute task with zero-padded ID -/tasks:execute-task 16 03 - -# Execute task from archived plan -/tasks:execute-task 12 05 -``` - -## Integration Notes - -This command is designed for scripting contexts where an external orchestrator manages task sequencing, commits, feature branches, linting, test execution, and plan archival. It integrates with the task management system by: -- Using established plan and task location patterns -- Leveraging the dependency checking script for validation -- Following status management conventions (see Valid Status Transitions) -- Providing structured machine-parseable output for orchestrator pipelines -- Maintaining compatibility with execute-blueprint workflows -- Preserving task isolation and dependency order - -The command complements execute-blueprint by providing granular single-task control while maintaining the same validation standards. diff --git a/.claude/commands/tasks/fix-broken-tests.md b/.claude/commands/tasks/fix-broken-tests.md deleted file mode 100644 index bc74129..0000000 --- a/.claude/commands/tasks/fix-broken-tests.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -argument-hint: "[testCommand]" -description: Fix the tests your task execution broke. ---- - -Fix all failing tests in this repository. - -Use tools for debugging. You are encouraged to write your own specialized tools to research, analyze, and debug -failing tests. You are not restricted to the stack of the current project to create your own -specialized tools. - -Execute this command to run the tests: - - -$1 - - -If the test command is empty, read CLAUDE.md for test execution instructions. - -⚠️ **CRITICAL INTEGRITY REQUIREMENT** ⚠️ -You MUST fix the actual bugs in the source code. Green tests are worthless if achieved through cheating. - -**This is CHEATING (absolutely forbidden):** -- Skipping tests with conditionals -- Modifying test assertions to pass -- Adding test-environment-specific code to source -- Disabling or commenting out tests -- ANY workaround that doesn't fix the real bug - -**This is THE RIGHT WAY:** -- Find the root cause in the source code -- Fix the actual bug -- Ensure tests pass because the code truly works - -**Process:** -1. Run all tests to identify failures -2. Fix EVERY failing test iteratively -3. Verify all tests pass legitimately - -DO NOT STOP after fixing some tests - fix ALL of them. - -Remember: The entire point of tests is to ensure code robustness. If you cheat in ANY way, the tests become meaningless and I cannot trust that the code actually works. - -If you get stuck and cannot fix a test properly, ask for help rather than resorting to shortcuts. diff --git a/.claude/commands/tasks/full-workflow.md b/.claude/commands/tasks/full-workflow.md deleted file mode 100644 index b8ada41..0000000 --- a/.claude/commands/tasks/full-workflow.md +++ /dev/null @@ -1,840 +0,0 @@ ---- -argument-hint: "[userPrompt]" -description: Execute the full workflow from plan creation to blueprint execution. ---- - -# Full Workflow Execution - -You are a workflow composition assistant. Your role is to execute the complete task management workflow from plan creation through blueprint execution **without pausing between steps**. This is a fully automated workflow that executes all three steps sequentially. - ---- - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -## Workflow Execution Instructions - -**CRITICAL**: Execute all three steps sequentially without waiting for user input between steps. Progress indicators are for user visibility only - do not pause execution. - -The user input is: - - -$ARGUMENTS - - -If no user input is provided, stop immediately and show an error message to the user. - -### Context Passing Between Steps - -**How information flows through the workflow:** -1. User provides prompt → use as input in Step 1 -2. Step 1 outputs "Plan ID: X" in structured format → extract X, use in Step 2 -3. Step 2 outputs "Tasks: Y" in structured format → use for progress tracking in Step 3 - -Use your internal Todo task tool to track the workflow execution: - -- [ ] Step 1: Create Plan -- [ ] Step 2: Generate Tasks -- [ ] Step 3: Execute Blueprint - ---- - -## Step 1: Plan Creation - -**Progress**: ⬛⬜⬜ 0% - Step 1/3: Starting Plan Creation - -Execute the following plan creation process: - -Use tools for the planning. You are encouraged to write your own specialized tools to research, analyze, and debug -any work order from the user. You are not restricted to the stack of the current project to create your own -specialized tools. - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -## Instructions - -Include $root/.ai/task-manager/config/TASK_MANAGER.md for the directory structure of tasks. - -The user input is: - - -$ARGUMENTS - - -If no user input is provided stop immediately and show an error message to the user. - -### Process Checklist - -Use your internal Todo task tool to track the following plan generation: - -- [ ] Read and execute $root/.ai/task-manager/config/hooks/PRE_PLAN.md -- [ ] User input and context analysis -- [ ] Clarification questions -- [ ] Plan generation -- [ ] Read and execute $root/.ai/task-manager/config/hooks/POST_PLAN.md - -#### Step 1: Context Analysis -Before creating any plan, analyze the user's request for: -- **Objective**: What is the end goal? -- **Scope**: What are the boundaries and constraints? -- **Resources**: What tools, libraries, or infrastructure are available? -- **Success Criteria**: How will success be measured? -- **Dependencies**: What prerequisites or blockers exist? -- **Technical Requirements**: What technologies or skills are needed? - -#### Step 2: Clarification Phase -If any critical context is missing: -1. Identify specific gaps in the information provided -2. Ask targeted follow-up questions -3. Frame questions clearly with examples when helpful -4. Be extra cautious. Users miss important context very often. Don't hesitate to ask for additional clarifications. - -Try to answer your own questions first by inspecting the codebase, docs, and assistant documents like CLAUDE.md, GEMINI.md, AGENTS.md ... - -IMPORTANT: Once you have the user's answers go back to Step 2. Do this in a loop until you have no more questions. Ask as many rounds of questions as necessary, it is very important you have all the information you need to achieve your task. - -#### Step 3: Plan Generation -Only after confirming sufficient context, create a plan according to the $root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md - -##### CRITICAL: Output Format - -Remember that a plan needs to be reviewed by a human. Be concise and to the point. Also, include mermaid diagrams to illustrate the plan. - -**Output Behavior: CRITICAL - Structured Output for Command Coordination** - -Always end your output with a standardized summary in this exact format, for command coordination: - -``` ---- - -Plan Summary: -- Plan ID: [numeric-id] -- Plan File: [full-path-to-plan-file] -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -###### Patterns to Avoid -Do not include the following in your plan output. -- Avoid time estimations -- Avoid task lists and mentions of phases (those are things we'll introduce later) -- Avoid code examples - -###### Frontmatter Structure - -Example: -```yaml ---- -id: 1 -summary: "Implement a comprehensive CI/CD pipeline using GitHub Actions for automated linting, testing, semantic versioning, and NPM publishing" -created: 2025-09-01 ---- -``` - -The schema for this frontmatter is: -```json -{ - "type": "object", - "required": ["id", "summary", "created"], - "properties": { - "id": { - "type": ["number"], - "description": "Unique identifier for the task. An integer." - }, - "summary": { - "type": "string", - "description": "A summary of the plan" - }, - "created": { - "type": "string", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "description": "Creation date in YYYY-MM-DD format" - } - }, - "additionalProperties": false -} -``` - -### Plan ID Generation - -Execute this script to determine the plan ID: - -```bash -next_id=$(node $root/config/scripts/get-next-plan-id.cjs) -``` - -**Key formatting:** -- **Front-matter**: Use numeric values (`id: 7`) -- **Directory names**: Use zero-padded strings (`07--plan-name`) - -**After completing Step 1:** -- Extract the Plan ID from the structured output -- Extract the Plan File path from the structured output - -**Progress**: ⬛⬜⬜ 33% - Step 1/3: Plan Creation Complete - ---- - -## Step 2: Task Generation - -**Progress**: ⬛⬜⬜ 33% - Step 2/3: Starting Task Generation - -Using the Plan ID extracted from Step 1, execute task generation: - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -You are a comprehensive task planning assistant. Your role is to create detailed, actionable plans based on user input while ensuring you have all necessary context before proceeding. - -Include `$root/.ai/task-manager/config/TASK_MANAGER.md` for the directory structure of tasks. - -## Instructions - -You will think hard to analyze the provided plan document and decompose it into atomic, actionable tasks with clear dependencies and groupings. - -Use your internal Todo task tool to track the following process: - -- [ ] Read and process plan [planId] -- [ ] Use the Task Generation Process to create tasks according to the Task Creation Guidelines -- [ ] Read and run the $root/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md - -### Input - -- A plan document. Extract it with the following command. - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] planFile) -``` - -### Input Error Handling -If the plan does not exist. Stop immediately and show an error to the user. - -### Task Creation Guidelines - -#### Task Minimization Principles -**Core Constraint:** Create only the minimum number of tasks necessary to satisfy the plan requirements. Target a 20-30% reduction from comprehensive task lists by questioning the necessity of each component. - -**Minimization Rules:** -- **Direct Implementation Only**: Create tasks for explicitly stated requirements, not "nice-to-have" features -- **DRY Task Principle**: Each task should have a unique, non-overlapping purpose -- **Question Everything**: For each task, ask "Is this absolutely necessary to meet the plan objectives?" -- **Avoid Gold-plating**: Resist the urge to add comprehensive features not explicitly required - -**Antipatterns to Avoid:** -- Creating separate tasks for "error handling" when it can be included in the main implementation -- Breaking simple operations into multiple tasks (e.g., separate "validate input" and "process input" tasks) -- Adding tasks for "future extensibility" or "best practices" not mentioned in the plan -- Creating comprehensive test suites for trivial functionality - -#### Task Granularity -Each task must be: -- **Single-purpose**: One clear deliverable or outcome -- **Atomic**: Cannot be meaningfully split further -- **Skill-specific**: Executable by a single skill agent (examples below) -- **Verifiable**: Has clear completion criteria - -#### Skill Selection and Technical Requirements - -**Core Principle**: Each task should require 1-2 specific technical skills that can be handled by specialized agents. Skills should be automatically inferred from the task's technical requirements and objectives. - -**Skill Selection Criteria**: -1. **Technical Specificity**: Choose skills that directly match the technical work required -2. **Agent Specialization**: Select skills that allow a single skilled agent to complete the task -3. **Minimal Overlap**: Avoid combining unrelated skill domains in a single task -4. **Creative Inference**: Derive skills from task objectives and implementation context - -**Inspirational Skill Examples** (use kebab-case format): -- Frontend: `react-components`, `css`, `js`, `vue-components`, `html` -- Backend: `api-endpoints`, `database`, `authentication`, `server-config` -- Testing: `jest`, `playwright`, `unit-testing`, `e2e-testing` -- DevOps: `docker`, `github-actions`, `deployment`, `ci-cd` -- Languages: `typescript`, `python`, `php`, `bash`, `sql` -- Frameworks: `nextjs`, `express`, `drupal-backend`, `wordpress-plugins` - -**Automatic Skill Inference Examples**: -- "Create user login form" → `["react-components", "authentication"]` -- "Build REST API for orders" → `["api-endpoints", "database"]` -- "Add Docker deployment" → `["docker", "deployment"]` -- "Write Jest tests for utils" → `["jest"]` - -**Assignment Guidelines**: -- **1 skill**: Focused, single-domain tasks -- **2 skills**: Tasks requiring complementary domains -- **Split if 3+**: Indicates task should be broken down - -``` -# Examples -skills: ["css"] # Pure styling -skills: ["api-endpoints", "database"] # API with persistence -skills: ["react-components", "jest"] # Implementation + testing -``` - -#### Meaningful Test Strategy Guidelines - -**IMPORTANT** Make sure to copy this _Meaningful Test Strategy Guidelines_ section into all the tasks focused on testing, and **also** keep them in mind when generating tasks. - -Your critical mantra for test generation is: "write a few tests, mostly integration". - -**Definition of "Meaningful Tests":** -Tests that verify custom business logic, critical paths, and edge cases specific to the application. Focus on testing YOUR code, not the framework or library functionality. - -**When TO Write Tests:** -- Custom business logic and algorithms -- Critical user workflows and data transformations -- Edge cases and error conditions for core functionality -- Integration points between different system components -- Complex validation logic or calculations - -**When NOT to Write Tests:** -- Third-party library functionality (already tested upstream) -- Framework features (React hooks, Express middleware, etc.) -- Simple CRUD operations without custom logic -- Getter/setter methods or basic property access -- Configuration files or static data -- Obvious functionality that would break immediately if incorrect - -**Test Task Creation Rules:** -- Combine related test scenarios into single tasks (e.g., "Test user authentication flow" not separate tasks for login, logout, validation) -- Focus on integration and critical path testing over unit test coverage -- Avoid creating separate tasks for testing each CRUD operation individually -- Question whether simple functions need dedicated test tasks - -### Task Generation Process - -#### Step 1: Task Decomposition -1. Read through the entire plan -2. Identify all concrete deliverables **explicitly stated** in the plan -3. Apply minimization principles: question necessity of each potential task -4. Break each deliverable into atomic tasks (only if genuinely needed) -5. Ensure no task requires multiple skill sets -6. Verify each task has clear inputs and outputs -7. **Minimize test tasks**: Combine related testing scenarios, avoid testing framework functionality -8. Be very detailed with the "Implementation Notes". This should contain enough detail for a non-thinking LLM model to successfully complete the task. Put these instructions in a collapsible field `
`. - -#### Step 2: Dependency Analysis -For each task, identify: -- **Hard dependencies**: Tasks that MUST complete before this can start -- **Soft dependencies**: Tasks that SHOULD complete for optimal execution -- **No circular dependencies**: Validate the dependency graph is acyclic - -Dependency Rule: Task B depends on Task A if: -- B requires output or artifacts from A -- B modifies code created by A -- B tests functionality implemented in A - -#### Step 3: Task Generation - -##### Frontmatter Structure - -Example: -```yaml ---- -id: 1 -group: "user-authentication" -dependencies: [] # List of task IDs, e.g., [2, 3] -status: "pending" # pending | in-progress | completed | needs-clarification -created: "2024-01-15" -skills: ["react-components", "authentication"] # Technical skills required for this task -# Optional: Include complexity scores for high-complexity tasks or decomposition tracking -# complexity_score: 4.2 # Composite complexity score (only if >4 or decomposed) -# complexity_notes: "Decomposed from original task due to high technical depth" ---- -``` - -The schema for this frontmatter is: -```json -{ - "type": "object", - "required": ["id", "group", "dependencies", "status", "created", "skills"], - "properties": { - "id": { - "type": ["number"], - "description": "Unique identifier for the task. An integer." - }, - "group": { - "type": "string", - "description": "Group or category the task belongs to" - }, - "dependencies": { - "type": "array", - "description": "List of task IDs this task depends on", - "items": { - "type": ["number"] - } - }, - "status": { - "type": "string", - "enum": ["pending", "in-progress", "completed", "needs-clarification"], - "description": "Current status of the task" - }, - "created": { - "type": "string", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "description": "Creation date in YYYY-MM-DD format" - }, - "skills": { - "type": "array", - "description": "Technical skills required for this task (1-2 skills recommended)", - "items": { - "type": "string", - "pattern": "^[a-z][a-z0-9-]*$" - }, - "minItems": 1, - "uniqueItems": true - }, - "complexity_score": { - "type": "number", - "minimum": 1, - "maximum": 10, - "description": "Optional: Composite complexity score (include only if >4 or for decomposed tasks)" - }, - "complexity_notes": { - "type": "string", - "description": "Optional: Rationale for complexity score or decomposition decisions" - } - }, - "additionalProperties": false -} -``` - -##### Task Body Structure - -Use the task template in $root/.ai/task-manager/config/templates/TASK_TEMPLATE.md - -##### Task ID Generation - -When creating tasks, you need to determine the next available task ID for the specified plan. Use this bash command to automatically generate the correct ID: - -```bash -node $root/config/scripts/get-next-task-id.cjs [planId] -``` - -### Validation Checklist -Before finalizing, ensure: - -**Core Task Requirements:** -- [ ] Each task has 1-2 appropriate technical skills assigned -- [ ] Skills are automatically inferred from task objectives and technical requirements -- [ ] All dependencies form an acyclic graph -- [ ] Task IDs are unique and sequential -- [ ] Groups are consistent and meaningful -- [ ] Every **explicitly stated** task from the plan is covered -- [ ] No redundant or overlapping tasks - -**Complexity Analysis & Controls:** -- [ ] **Complexity Analysis Complete**: All tasks assessed using 5-dimension scoring -- [ ] **Decomposition Applied**: Tasks with composite score ≥6 have been decomposed or justified -- [ ] **Final Task Complexity**: All final tasks have composite score ≤5 (target ≤4) -- [ ] **Iteration Limits Respected**: No task exceeded 3 decomposition rounds -- [ ] **Minimum Viability**: No tasks decomposed below complexity threshold of 3 -- [ ] **Quality Gates Passed**: All decomposed tasks meet enhanced quality criteria -- [ ] **Dependency Integrity**: No circular dependencies or orphaned tasks exist -- [ ] **Error Handling Complete**: All edge cases resolved or escalated appropriately - -**Complexity Documentation Requirements:** -- [ ] **Complexity Scores Documented**: Individual dimension scores recorded for complex tasks -- [ ] **Decomposition History**: Iteration tracking included in `complexity_notes` for decomposed tasks -- [ ] **Validation Status**: All tasks marked with appropriate validation outcomes -- [ ] **Escalation Documentation**: High-complexity tasks have clear escalation notes -- [ ] **Consistency Validated**: Complexity scores align with task descriptions and skills - -**Scope & Quality Control:** -- [ ] **Minimization Applied**: Each task is absolutely necessary (20-30% reduction target) -- [ ] **Test Tasks are Meaningful**: Focus on business logic, not framework functionality -- [ ] **No Gold-plating**: Only plan requirements are addressed -- [ ] **Total Task Count**: Represents minimum viable implementation -- [ ] **Scope Preservation**: Decomposed tasks collectively match original requirements - -**System Reliability:** -- [ ] **Error Conditions Resolved**: No unresolved error states remain -- [ ] **Manual Intervention Flagged**: Complex edge cases properly escalated -- [ ] **Quality Checkpoints**: All validation gates completed successfully -- [ ] **Dependency Graph Validated**: Full dependency analysis confirms acyclic, logical relationships - -### Error Handling -If the plan lacks sufficient detail: -- Note areas needing clarification -- Create placeholder tasks marked with `status: "needs-clarification"` -- Document assumptions made - -#### Step 4: POST_TASK_GENERATION_ALL hook - -Read and run the $root/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md - -### Output Requirements - -**Output Behavior:** - -Provide a concise completion message with task count and location: -- Example: "Task generation complete. Created [count] tasks in `$root/.ai/task-manager/plans/[plan-id]--[name]/tasks/`" - -**CRITICAL - Structured Output for Command Coordination:** - -Always end your output with a standardized summary in this exact format: - -``` ---- -Task Generation Summary: -- Plan ID: [numeric-id] -- Tasks: [count] -- Status: Ready for execution -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -**Progress**: ⬛⬛⬜ 66% - Step 2/3: Task Generation Complete - ---- - -## Step 3: Blueprint Execution - -**Progress**: ⬛⬛⬜ 66% - Step 3/3: Starting Blueprint Execution - -Using the Plan ID from previous steps, execute the blueprint: - -You are the coordinator responsible for executing all tasks defined in the execution blueprint of a plan document, so choose an appropriate sub-agent for this role. Your role is to coordinate phase-by-phase execution, manage parallel task processing, and ensure validation gates pass before phase transitions. - -## Critical Rules - -1. **Never skip validation gates** - Phase progression requires successful validation -2. **Maintain task isolation** - Parallel tasks must not interfere with each other -3. **Preserve dependency order** - Never execute a task before its dependencies -4. **Document everything** - All decisions, issues, and outcomes must be recorded in the "Execution Summary", under "Noteworthy Events" -5. **Fail safely** - Better to halt and request help than corrupt the execution state - -## Input Requirements -- A plan document with an execution blueprint section. See /TASK_MANAGER.md to find the plan with ID [planId] -- Task files with frontmatter metadata (id, group, dependencies, status) -- Validation gates document: `/config/hooks/POST_PHASE.md` - -### Input Error Handling - -If the plan does not exist, stop immediately and show an error to the user. - -**Note**: If tasks or the execution blueprint section are missing, they will be automatically generated before execution begins (see Task and Blueprint Validation below). - -### Task and Blueprint Validation - -Before proceeding with execution, validate that tasks exist and the execution blueprint has been generated. If either is missing, automatically invoke task generation. - -**Validation Steps:** - -First, discover the task manager root directory: - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -Then extract validation results: - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] planFile) -plan_dir=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] planDir) -task_count=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] taskCount) -blueprint_exists=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] blueprintExists) -``` - -4. **Automatic task generation**: - -If either `$task_count` is 0 or `$blueprint_exists` is "no": - - Display notification to user: "⚠️ Tasks or execution blueprint not found. Generating tasks automatically..." - - Execute the embedded task generation process below - - ## Embedded Task Generation - - Follow ALL instructions from `.*/**/generate-tasks.md` exactly for plan ID [planId]. It is important that you find and read the `generate-tasks.md` command first. - - This includes: - - Reading and processing the plan document - - Applying task minimization principles (20-30% reduction target) - - Creating atomic tasks with 1-2 skills each - - Generating proper task files with frontmatter and body structure - - Running all validation checklists - - Executing the POST_TASK_GENERATION_ALL hook - - ## Resume Blueprint Execution - - After task generation completes, continue with execution below. - -Otherwise, if tasks exist, proceed directly to execution. - -## Execution Process - -Use your internal Todo task tool to track the execution of all phases, and the final update of the plan with the summary. Example: - -- [ ] Create feature branch via `node $root/config/scripts/create-feature-branch.cjs [planId]` -- [ ] Validate or auto-generate tasks and execution blueprint if missing. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 1. -- [ ] Phase 1: Execute 1 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 1. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 2. -- [ ] Phase 2: Execute 3 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 2. -- [ ] Execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md hook before Phase 3. -- [ ] Phase 3: Execute 1 task(s) in parallel. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_PHASE.md hook after Phase 3. -- [ ] Execute $root/.ai/task-manager/config/hooks/POST_EXECUTION.md hook after all phases complete. -- [ ] Update the Plan 7 with execution summary using $root/.ai/task-manager/config/hooks/EXECUTION_SUMMARY_TEMPLATE.md. -- [ ] Archive Plan 7. - -### Phase Pre-Execution - -Read and execute $root/.ai/task-manager/config/hooks/PRE_PHASE.md - -### Phase Execution Workflow - -1. **Phase Initialization** - - Identify current phase from the execution blueprint - - List all tasks scheduled for parallel execution in this phase - -2. **Agent Selection and Task Assignment** -Read and execute $root/.ai/task-manager/config/hooks/PRE_TASK_ASSIGNMENT.md - -3. **Parallel Execution** - - Deploy all selected agents simultaneously using your internal Task tool - - Monitor execution progress for each task - - Capture outputs and artifacts from each agent - - Update task status in real-time - -4. **Phase Completion Verification** - - Ensure all tasks in the phase have status: "completed" - - Collect and review all task outputs - - Document any issues or exceptions encountered - -### Phase Post-Execution - -Read and execute $root/.ai/task-manager/config/hooks/POST_PHASE.md - - -### Phase Transition - - - Update phase status to "completed" in the Blueprint section of the plan [planId] document. - - Initialize next phase - - Repeat process until all phases are complete - -### Error Handling - -#### Validation Gate Failures -Read and execute $root/.ai/task-manager/config/hooks/POST_ERROR_DETECTION.md - -### Output Requirements - -**Output Behavior:** - -Provide a concise execution summary: -- Example: "Execution completed. Review summary: `$root/.ai/task-manager/archive/[plan]/plan-[id].md`" - -**CRITICAL - Structured Output for Command Coordination:** - -Always end your output with a standardized summary in this exact format: - -``` ---- -Execution Summary: -- Plan ID: [numeric-id] -- Status: Archived -- Location: $root/.ai/task-manager/archive/[plan-id]--[plan-name]/ -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. - -## Optimization Guidelines - -- **Maximize parallelism**: Always run all available tasks in a phase simultaneously -- **Resource awareness**: Balance agent allocation with system capabilities -- **Early failure detection**: Monitor tasks actively to catch issues quickly -- **Continuous improvement**: Note patterns for future blueprint optimization - -## Post-Execution Processing - -Upon successful completion of all phases and validation gates, perform the following additional steps: - -- [ ] Post-Execution Validation -- [ ] Execution Summary Generation -- [ ] Plan Archival - -### 0. Post-Execution Validation - -Read and execute $root/.ai/task-manager/config/hooks/POST_EXECUTION.md - -If validation fails, halt execution. The plan remains in `plans/` for debugging. - -### 1. Execution Summary Generation - -Append an execution summary section to the plan document with the format described in $root/.ai/task-manager/config/templates/EXECUTION_SUMMARY_TEMPLATE.md - -### 2. Plan Archival - -After successfully appending the execution summary: - -**Move completed plan to archive**: -```bash -mv $root/.ai/task-manager/plans/[plan-folder] $root/.ai/task-manager/archive/ -``` - -### Important Notes - -- **Only archive on complete success**: Archive operations should only occur when ALL phases are completed and ALL validation gates have passed -- **Failed executions remain active**: Plans that fail execution or validation should remain in the `plans/` directory for debugging and potential re-execution -- **Error handling**: If archival fails, log the error but do not fail the overall execution - the implementation work is complete -- **Preserve structure**: The entire plan folder (including all tasks and subdirectories) should be moved as-is to maintain referential integrity - -**Progress**: ⬛⬛⬛ 100% - Step 3/3: Blueprint Execution Complete - ---- - -## Final Summary - -Generate an extremely concise final summary using the structured output from Step 3. diff --git a/.claude/commands/tasks/generate-tasks.md b/.claude/commands/tasks/generate-tasks.md deleted file mode 100644 index ff4e741..0000000 --- a/.claude/commands/tasks/generate-tasks.md +++ /dev/null @@ -1,348 +0,0 @@ ---- -argument-hint: "[planId]" -description: Generate tasks to implement the plan with the provided ID. ---- - -# Comprehensive Task List Creation - ---- - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -You are a comprehensive task planning assistant. Your role is to create detailed, actionable plans based on user input while ensuring you have all necessary context before proceeding. - -Include `$root/.ai/task-manager/config/TASK_MANAGER.md` for the directory structure of tasks. - -## Instructions - -You will think hard to analyze the provided plan document and decompose it into atomic, actionable tasks with clear dependencies and groupings. - -Use your internal Todo task tool to track the following process: - -- [ ] Read and process plan $1 -- [ ] Use the Task Generation Process to create tasks according to the Task Creation Guidelines -- [ ] Read and run the $root/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md - -### Input - -- A plan document. Extract it with the following command. - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile) -``` - -### Input Error Handling -If the plan does not exist. Stop immediately and show an error to the user. - -### Task Creation Guidelines - -#### Task Minimization Principles -**Core Constraint:** Create only the minimum number of tasks necessary to satisfy the plan requirements. Target a 20-30% reduction from comprehensive task lists by questioning the necessity of each component. - -**Minimization Rules:** -- **Direct Implementation Only**: Create tasks for explicitly stated requirements, not "nice-to-have" features -- **DRY Task Principle**: Each task should have a unique, non-overlapping purpose -- **Question Everything**: For each task, ask "Is this absolutely necessary to meet the plan objectives?" -- **Avoid Gold-plating**: Resist the urge to add comprehensive features not explicitly required - -**Antipatterns to Avoid:** -- Creating separate tasks for "error handling" when it can be included in the main implementation -- Breaking simple operations into multiple tasks (e.g., separate "validate input" and "process input" tasks) -- Adding tasks for "future extensibility" or "best practices" not mentioned in the plan -- Creating comprehensive test suites for trivial functionality - -#### Task Granularity -Each task must be: -- **Single-purpose**: One clear deliverable or outcome -- **Atomic**: Cannot be meaningfully split further -- **Skill-specific**: Executable by a single skill agent (examples below) -- **Verifiable**: Has clear completion criteria - -#### Skill Selection and Technical Requirements - -**Core Principle**: Each task should require 1-2 specific technical skills that can be handled by specialized agents. Skills should be automatically inferred from the task's technical requirements and objectives. - -**Skill Selection Criteria**: -1. **Technical Specificity**: Choose skills that directly match the technical work required -2. **Agent Specialization**: Select skills that allow a single skilled agent to complete the task -3. **Minimal Overlap**: Avoid combining unrelated skill domains in a single task -4. **Creative Inference**: Derive skills from task objectives and implementation context - -**Inspirational Skill Examples** (use kebab-case format): -- Frontend: `react-components`, `css`, `js`, `vue-components`, `html` -- Backend: `api-endpoints`, `database`, `authentication`, `server-config` -- Testing: `jest`, `playwright`, `unit-testing`, `e2e-testing` -- DevOps: `docker`, `github-actions`, `deployment`, `ci-cd` -- Languages: `typescript`, `python`, `php`, `bash`, `sql` -- Frameworks: `nextjs`, `express`, `drupal-backend`, `wordpress-plugins` - -**Automatic Skill Inference Examples**: -- "Create user login form" → `["react-components", "authentication"]` -- "Build REST API for orders" → `["api-endpoints", "database"]` -- "Add Docker deployment" → `["docker", "deployment"]` -- "Write Jest tests for utils" → `["jest"]` - -**Assignment Guidelines**: -- **1 skill**: Focused, single-domain tasks -- **2 skills**: Tasks requiring complementary domains -- **Split if 3+**: Indicates task should be broken down - -``` -# Examples -skills: ["css"] # Pure styling -skills: ["api-endpoints", "database"] # API with persistence -skills: ["react-components", "jest"] # Implementation + testing -``` - -#### Meaningful Test Strategy Guidelines - -**IMPORTANT** Make sure to copy this _Meaningful Test Strategy Guidelines_ section into all the tasks focused on testing, and **also** keep them in mind when generating tasks. - -Your critical mantra for test generation is: "write a few tests, mostly integration". - -**Definition of "Meaningful Tests":** -Tests that verify custom business logic, critical paths, and edge cases specific to the application. Focus on testing YOUR code, not the framework or library functionality. - -**When TO Write Tests:** -- Custom business logic and algorithms -- Critical user workflows and data transformations -- Edge cases and error conditions for core functionality -- Integration points between different system components -- Complex validation logic or calculations - -**When NOT to Write Tests:** -- Third-party library functionality (already tested upstream) -- Framework features (React hooks, Express middleware, etc.) -- Simple CRUD operations without custom logic -- Getter/setter methods or basic property access -- Configuration files or static data -- Obvious functionality that would break immediately if incorrect - -**Test Task Creation Rules:** -- Combine related test scenarios into single tasks (e.g., "Test user authentication flow" not separate tasks for login, logout, validation) -- Focus on integration and critical path testing over unit test coverage -- Avoid creating separate tasks for testing each CRUD operation individually -- Question whether simple functions need dedicated test tasks - -### Task Generation Process - -#### Step 1: Task Decomposition -1. Read through the entire plan -2. Identify all concrete deliverables **explicitly stated** in the plan -3. Apply minimization principles: question necessity of each potential task -4. Break each deliverable into atomic tasks (only if genuinely needed) -5. Ensure no task requires multiple skill sets -6. Verify each task has clear inputs and outputs -7. **Minimize test tasks**: Combine related testing scenarios, avoid testing framework functionality -8. Be very detailed with the "Implementation Notes". This should contain enough detail for a non-thinking LLM model to successfully complete the task. Put these instructions in a collapsible field `
`. - -#### Step 2: Dependency Analysis -For each task, identify: -- **Hard dependencies**: Tasks that MUST complete before this can start -- **Soft dependencies**: Tasks that SHOULD complete for optimal execution -- **No circular dependencies**: Validate the dependency graph is acyclic - -Dependency Rule: Task B depends on Task A if: -- B requires output or artifacts from A -- B modifies code created by A -- B tests functionality implemented in A - -#### Step 3: Task Generation - -##### Frontmatter Structure - -Example: -```yaml ---- -id: 1 -group: "user-authentication" -dependencies: [] # List of task IDs, e.g., [2, 3] -status: "pending" # pending | in-progress | completed | needs-clarification -created: "2024-01-15" -skills: ["react-components", "authentication"] # Technical skills required for this task -# Optional: Include complexity scores for high-complexity tasks or decomposition tracking -# complexity_score: 4.2 # Composite complexity score (only if >4 or decomposed) -# complexity_notes: "Decomposed from original task due to high technical depth" ---- -``` - -The schema for this frontmatter is: -```json -{ - "type": "object", - "required": ["id", "group", "dependencies", "status", "created", "skills"], - "properties": { - "id": { - "type": ["number"], - "description": "Unique identifier for the task. An integer." - }, - "group": { - "type": "string", - "description": "Group or category the task belongs to" - }, - "dependencies": { - "type": "array", - "description": "List of task IDs this task depends on", - "items": { - "type": ["number"] - } - }, - "status": { - "type": "string", - "enum": ["pending", "in-progress", "completed", "needs-clarification"], - "description": "Current status of the task" - }, - "created": { - "type": "string", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$", - "description": "Creation date in YYYY-MM-DD format" - }, - "skills": { - "type": "array", - "description": "Technical skills required for this task (1-2 skills recommended)", - "items": { - "type": "string", - "pattern": "^[a-z][a-z0-9-]*$" - }, - "minItems": 1, - "uniqueItems": true - }, - "complexity_score": { - "type": "number", - "minimum": 1, - "maximum": 10, - "description": "Optional: Composite complexity score (include only if >4 or for decomposed tasks)" - }, - "complexity_notes": { - "type": "string", - "description": "Optional: Rationale for complexity score or decomposition decisions" - } - }, - "additionalProperties": false -} -``` - -##### Task Body Structure - -Use the task template in $root/.ai/task-manager/config/templates/TASK_TEMPLATE.md - -##### Task ID Generation - -When creating tasks, you need to determine the next available task ID for the specified plan. Use this bash command to automatically generate the correct ID: - -```bash -node $root/config/scripts/get-next-task-id.cjs $1 -``` - -### Validation Checklist -Before finalizing, ensure: - -**Core Task Requirements:** -- [ ] Each task has 1-2 appropriate technical skills assigned -- [ ] Skills are automatically inferred from task objectives and technical requirements -- [ ] All dependencies form an acyclic graph -- [ ] Task IDs are unique and sequential -- [ ] Groups are consistent and meaningful -- [ ] Every **explicitly stated** task from the plan is covered -- [ ] No redundant or overlapping tasks - -**Complexity Analysis & Controls:** -- [ ] **Complexity Analysis Complete**: All tasks assessed using 5-dimension scoring -- [ ] **Decomposition Applied**: Tasks with composite score ≥6 have been decomposed or justified -- [ ] **Final Task Complexity**: All final tasks have composite score ≤5 (target ≤4) -- [ ] **Iteration Limits Respected**: No task exceeded 3 decomposition rounds -- [ ] **Minimum Viability**: No tasks decomposed below complexity threshold of 3 -- [ ] **Quality Gates Passed**: All decomposed tasks meet enhanced quality criteria -- [ ] **Dependency Integrity**: No circular dependencies or orphaned tasks exist -- [ ] **Error Handling Complete**: All edge cases resolved or escalated appropriately - -**Complexity Documentation Requirements:** -- [ ] **Complexity Scores Documented**: Individual dimension scores recorded for complex tasks -- [ ] **Decomposition History**: Iteration tracking included in `complexity_notes` for decomposed tasks -- [ ] **Validation Status**: All tasks marked with appropriate validation outcomes -- [ ] **Escalation Documentation**: High-complexity tasks have clear escalation notes -- [ ] **Consistency Validated**: Complexity scores align with task descriptions and skills - -**Scope & Quality Control:** -- [ ] **Minimization Applied**: Each task is absolutely necessary (20-30% reduction target) -- [ ] **Test Tasks are Meaningful**: Focus on business logic, not framework functionality -- [ ] **No Gold-plating**: Only plan requirements are addressed -- [ ] **Total Task Count**: Represents minimum viable implementation -- [ ] **Scope Preservation**: Decomposed tasks collectively match original requirements - -**System Reliability:** -- [ ] **Error Conditions Resolved**: No unresolved error states remain -- [ ] **Manual Intervention Flagged**: Complex edge cases properly escalated -- [ ] **Quality Checkpoints**: All validation gates completed successfully -- [ ] **Dependency Graph Validated**: Full dependency analysis confirms acyclic, logical relationships - -### Error Handling -If the plan lacks sufficient detail: -- Note areas needing clarification -- Create placeholder tasks marked with `status: "needs-clarification"` -- Document assumptions made - -#### Step 4: POST_TASK_GENERATION_ALL hook - -Read and run the $root/.ai/task-manager/config/hooks/POST_TASK_GENERATION_ALL.md - -### Output Requirements - -**Output Behavior:** - -Provide a concise completion message with task count and location: -- Example: "Task generation complete. Created [count] tasks in `$root/.ai/task-manager/plans/[plan-id]--[name]/tasks/`" - -**CRITICAL - Structured Output for Command Coordination:** - -Always end your output with a standardized summary in this exact format: - -``` ---- -Task Generation Summary: -- Plan ID: [numeric-id] -- Tasks: [count] -- Status: Ready for execution -``` - -This structured output enables automated workflow coordination and must be included even when running standalone. diff --git a/.claude/commands/tasks/refine-plan-auto.md b/.claude/commands/tasks/refine-plan-auto.md deleted file mode 100644 index 01d3d95..0000000 --- a/.claude/commands/tasks/refine-plan-auto.md +++ /dev/null @@ -1,172 +0,0 @@ - ---- -argument-hint: "[planId]" -description: Review and refine a plan without user interaction, resolving ambiguities autonomously. ---- -# Plan Review and Refinement (Autonomous Mode) - -You are a strategic planning specialist who specializes in interrogating existing plans, uncovering blind spots, and -refining the document so that task generators receive the clearest possible instructions. Treat the current plan as the -work product of another assistant: your responsibility is to pressure test it, resolve any missing information -autonomously, and update the plan with the refinements. Use the plan-creator sub-agent for this if it is available. - -**AUTONOMOUS MODE**: This command runs without user interaction. You must resolve all ambiguities by inspecting the -codebase, documentation, and project context. Do NOT ask the user any questions or wait for user input at any point. - ---- - -Use tools for the plan refinement. You are encouraged to write your own specialized tools to research, analyze, and -debug any plan refinement. You are not restricted to the stack of the current project to create your own specialized -tools. - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -Include `$root/.ai/task-manager/config/TASK_MANAGER.md` to understand the plan directory structure and naming conventions. - -## Inputs -- **Plan ID**: `$1` (required) -- **Optional refinement notes**: Either provided as additional command arguments or in the conversation. Treat them as constraints that must be reflected in the refined plan. - -If the plan ID is missing, immediately stop and show an error explaining correct usage. - -### Plan Discovery and Validation - -Obtain the plan using the plan ID: - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile) -``` - -## Process Checklist - -Use your internal Todo tool to track the entire refinement workflow: - -- [ ] Load `$root/.ai/task-manager/config/hooks/PRE_PLAN.md` -- [ ] Stage 1: Baseline Review -- [ ] Stage 2: Autonomous Clarification -- [ ] Stage 3: Refinement Implementation -- [ ] Review the existing plan end-to-end (frontmatter, clarifications, architecture, risks, etc.) -- [ ] Surface strengths, contradictions, and potential risks, without updating the plan -- [ ] Use the "Autonomous Clarification Algorithm" to resolve gaps via codebase inspection -- [ ] Apply refinements using `$root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md` as the structural baseline -- [ ] Update the "Plan Clarifications" table with findings and assumptions -- [ ] Update the plan file (stored in `plan_file`) with the refinements from steps above -- [ ] Re-run `$root/.ai/task-manager/config/hooks/POST_PLAN.md` - -## Stage 1: Baseline Review - -1. Capture key metadata (plan title, summary, creation date, related initiatives). -2. Provide a concise plan overview for the user and highlight the strongest sections. - -## Stage 2: Autonomous Clarification - -- Use the "Autonomous Clarification Algorithm" below to resolve gaps without user input -- Record findings in the "Plan Clarifications" section using the existing format (table with question/answer pairs), marking the source as "auto-resolved" or "assumption" -- For truly unresolvable questions, record them as unresolved with mitigation notes so downstream assistants know the risk - -### Autonomous Clarification Algorithm - -Think harder before flagging gaps—only document concrete uncertainties you can cite. - -1. Ask yourself: **"Are there any aspects of the plan that could benefit from further clarification?"** Identify gaps using these lenses: - - **Context gaps**: missing background, assumptions, competing priorities. - - **Technical gaps**: underspecified architecture, unclear interfaces, missing diagrams. - - **Risk gaps**: untracked risks, missing mitigations, hand-wavy success metrics. - - **Scope issues**: gold-plating, ambiguous boundaries, requirements that contradict YAGNI. -2. Document each gap with `{section, issue, severity, proposed fix}` so you can reference it when refining the plan. -3. For each gap, attempt to resolve it by: - - Inspecting the codebase, configuration files, and documentation - - Analyzing existing patterns and conventions in the project - - Reviewing assistant documents (CLAUDE.md, GEMINI.md, AGENTS.md) and README files - - Making reasonable assumptions based on common practices and project context -4. Record all resolutions and assumptions in the Plan Clarifications table with clear rationale. Mark each entry's source as either "auto-resolved" (confirmed via codebase) or "assumption" (best-effort guess). -5. If no gaps remain (or all have been resolved/documented), proceed directly to Stage 3. - -CRITICAL: Do NOT ask the user any questions. Do NOT wait for user input. Resolve all ambiguity through codebase analysis and documented assumptions. - -```mermaid -flowchart TD - A[Inspect current plan] --> B{Need more clarification?} - B -- No --> C[End · proceed with refinement] - B -- Yes --> D[Attempt to resolve via codebase inspection] - D --> E{Resolved?} - E -- Yes --> F[Record as auto-resolved] - E -- No --> G[Record assumption with rationale] - F --> B - G --> B -``` - -## Stage 3: Refinement Implementation - -Once you have sufficient context (or have documented the missing context), refine the plan directly in-place: - -1. **Maintain Identity**: Keep the existing `id` and directory. Do not create a new plan ID. -2. **Structure Compliance**: Ensure the plan still follows `$root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md`. Add missing sections if necessary. -3. **Content Updates**: - - Refresh the executive summary to reflect clarifications and new insights. - - Update architectural sections, diagrams, and risk mitigations to resolve the identified gaps. - - Trim any scope creep that is not explicitly required. - - Clearly reference clarifications in the relevant plan sections (e.g., italicized notes that point back to the Q&A table). -4. **Net-New Sections**: If the plan needs a new subsection (e.g., Decision Log, Data Contracts), add it under `Notes` with a clearly labeled section so it remains discoverable. -5. **Change Log**: Append a bullet list in the `Notes` section that briefly states what changed in this refinement session (e.g., `- 2025-03-16: Clarified auth flow tokens and updated architecture diagram`). -6. **Validation Hooks**: Execute `$root/.ai/task-manager/config/hooks/POST_PLAN.md` to ensure the refined plan still meets quality bars. - -## Output Requirements - -1. Present a concise "Refinement Report" to the user containing: - - Snapshot of the updated plan summary (title, summary line, plan path). - - Key clarifications added (with links to sections if applicable). - - Major improvements and remaining open questions (if any). -2. Ensure the plan file on disk is fully updated before finishing. - -## Structured Output (MANDATORY) - -Always end with the standardized summary so orchestrators can chain commands: - -``` ---- - -Plan Refinement Summary: -- Plan ID: [numeric-id] -- Plan File: [full-path-to-plan-file] -``` diff --git a/.claude/commands/tasks/refine-plan.md b/.claude/commands/tasks/refine-plan.md deleted file mode 100644 index 9ffeb0b..0000000 --- a/.claude/commands/tasks/refine-plan.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -argument-hint: "[planId]" -description: Review the plan with the provided ID, gather clarifications, and refine it. ---- -# Plan Review and Refinement - -You are a strategic planning specialist who specializes in interrogating existing plans, uncovering blind spots, and -refining the document so that task generators receive the clearest possible instructions. Treat the current plan as the -work product of another assistant: your responsibility is to pressure test it, request any missing information from the -user, and update the plan with the refinements. Use the plan-creator sub-agent for this if it is available. - ---- - -Use tools for the plan refinement. You are encouraged to write your own specialized tools to research, analyze, and -debug any plan refinement. You are not restricted to the stack of the current project to create your own specialized -tools. - -## Find the AI Task Manager root - -```bash -if [ ! -f /tmp/find-ai-task-manager-root.js ]; then - cat << 'EOF' > /tmp/find-ai-task-manager-root.js -const fs = require('fs'); -const path = require('path'); - -const findRoot = (currentDir) => { - const taskManagerPath = path.join(currentDir, '.ai/task-manager'); - const metadataPath = path.join(taskManagerPath, '.init-metadata.json'); - - try { - if (fs.existsSync(metadataPath) && JSON.parse(fs.readFileSync(metadataPath, 'utf8')).version) { - console.log(path.resolve(taskManagerPath)); - process.exit(0); - } - } catch (e) { - // Continue searching - } - - const parentDir = path.dirname(currentDir); - if (parentDir.length < currentDir.length) { - findRoot(parentDir); - } else { - process.exit(1); - } -}; - -findRoot(process.cwd()); -EOF -fi - -root=$(node /tmp/find-ai-task-manager-root.js) - -if [ -z "$root" ]; then - echo "Error: Could not find task manager root directory (.ai/task-manager)" - exit 1 -fi -``` - -Include `$root/.ai/task-manager/config/TASK_MANAGER.md` to understand the plan directory structure and naming conventions. - -## Inputs -- **Plan ID**: `$1` (required) -- **Optional refinement notes**: Either provided as additional command arguments or in the conversation. Treat them as constraints that must be reflected in the refined plan. - -If the plan ID is missing, immediately stop and show an error explaining correct usage. - -### Plan Discovery and Validation - -Obtain the plan using the plan ID: - -```bash -# Extract validation results directly from script -plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile) -``` - -## Process Checklist - -Use your internal Todo tool to track the entire refinement workflow: - -- [ ] Load `$root/.ai/task-manager/config/hooks/PRE_PLAN.md` -- [ ] Stage 1: Baseline Review -- [ ] Stage 2: Clarification Loop -- [ ] Stage 3: Refinement Implementation -- [ ] Review the existing plan end-to-end (frontmatter, clarifications, architecture, risks, etc.) -- [ ] Surface strengths, contradictions, and potential risks, without updating the plan -- [ ] Use the "Total Clarification Algorithm" to get the missing clarification from the user -- [ ] Apply refinements using `$root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md` as the structural baseline -- [ ] Update the "Plan Clarifications" table with the latest Q&A -- [ ] Update the plan file (stored in `plan_file`) with the refinements from steps above -- [ ] Re-run `$root/.ai/task-manager/config/hooks/POST_PLAN.md` - -## Stage 1: Baseline Review - -1. Capture key metadata (plan title, summary, creation date, related initiatives). -2. Provide a concise plan overview for the user and highlight the strongest sections. - -## Stage 2: Clarification Loop - -- Use the "Total Clarification Algorithm" to get the missing clarification from the user -- After receiving answers, append them to the "Plan Clarifications" section in the plan Markdown using the existing format (table with question/answer pairs). -- If the user cannot answer, record the unresolved questions along with mitigation notes so downstream assistants know the risk. - -### Total Clarification Algorithm - -Think harder before interrupting the user—only trigger this loop when you can cite concrete uncertainties. - -1. Ask yourself: **“Are there any aspects of the plan that could benefit from further clarification?”** Identify gaps using these lenses: - - **Context gaps**: missing background, assumptions, competing priorities. - - **Technical gaps**: underspecified architecture, unclear interfaces, missing diagrams. - - **Risk gaps**: untracked risks, missing mitigations, hand-wavy success metrics. - - **Scope issues**: gold-plating, ambiguous boundaries, requirements that contradict YAGNI. -2. Document each gap with `{section, issue, severity, proposed fix}` so you can reference it when refining the plan. -3. If the answer is **No**, stop here and continue refining the plan with the context already available. -4. If the answer is **Yes**: - - Build a clarification packet grouped by theme. - - Prefill each question with the most plausible answer so the user can confirm/deny quickly. - - Always include an **“Other / open-ended”** option to capture nuances you did not anticipate. -5. **STOP AND ASK**: Present the clarification packet to the user. **You must halt execution here and await user input.** Do not simulate the user's response. Do not proceed to Stage 3 until you have received explicit answers. - -```mermaid -flowchart TD - A[Inspect current plan] --> B{Need more clarification?} - B -- No --> C[End · proceed with refinement] - B -- Yes --> D[Construct Question Packet] - D --> E[STOP · Ask User] - E --> F[Receive Input] - F --> B -``` - -## Stage 3: Refinement Implementation - -Once you have sufficient context (or have documented the missing context), refine the plan directly in-place: - -1. **Maintain Identity**: Keep the existing `id` and directory. Do not create a new plan ID. -2. **Structure Compliance**: Ensure the plan still follows `$root/.ai/task-manager/config/templates/PLAN_TEMPLATE.md`. Add missing sections if necessary. -3. **Content Updates**: - - Refresh the executive summary to reflect clarifications and new insights. - - Update architectural sections, diagrams, and risk mitigations to resolve the identified gaps. - - Trim any scope creep that is not explicitly required. - - Clearly reference clarifications in the relevant plan sections (e.g., italicized notes that point back to the Q&A table). -4. **Net-New Sections**: If the plan needs a new subsection (e.g., Decision Log, Data Contracts), add it under `Notes` with a clearly labeled section so it remains discoverable. -5. **Change Log**: Append a bullet list in the `Notes` section that briefly states what changed in this refinement session (e.g., `- 2025-03-16: Clarified auth flow tokens and updated architecture diagram`). -6. **Validation Hooks**: Execute `$root/.ai/task-manager/config/hooks/POST_PLAN.md` to ensure the refined plan still meets quality bars. - -## Output Requirements - -1. Present a concise "Refinement Report" to the user containing: - - Snapshot of the updated plan summary (title, summary line, plan path). - - Key clarifications added (with links to sections if applicable). - - Major improvements and remaining open questions (if any). -2. Ensure the plan file on disk is fully updated before finishing. - -## Structured Output (MANDATORY) - -Always end with the standardized summary so orchestrators can chain commands: - -``` ---- - -Plan Refinement Summary: -- Plan ID: [numeric-id] -- Plan File: [full-path-to-plan-file] -``` diff --git a/.claude/skills/st-code-review b/.claude/skills/st-code-review new file mode 120000 index 0000000..4c0d3b5 --- /dev/null +++ b/.claude/skills/st-code-review @@ -0,0 +1 @@ +../../.agents/skills/st-code-review \ No newline at end of file diff --git a/.claude/skills/st-create-plan b/.claude/skills/st-create-plan new file mode 120000 index 0000000..fd31e2b --- /dev/null +++ b/.claude/skills/st-create-plan @@ -0,0 +1 @@ +../../.agents/skills/st-create-plan \ No newline at end of file diff --git a/.claude/skills/st-execute-blueprint b/.claude/skills/st-execute-blueprint new file mode 120000 index 0000000..af0c43d --- /dev/null +++ b/.claude/skills/st-execute-blueprint @@ -0,0 +1 @@ +../../.agents/skills/st-execute-blueprint \ No newline at end of file diff --git a/.claude/skills/st-execute-task b/.claude/skills/st-execute-task new file mode 120000 index 0000000..cfbc8f9 --- /dev/null +++ b/.claude/skills/st-execute-task @@ -0,0 +1 @@ +../../.agents/skills/st-execute-task \ No newline at end of file diff --git a/.claude/skills/st-full-workflow b/.claude/skills/st-full-workflow new file mode 120000 index 0000000..86403af --- /dev/null +++ b/.claude/skills/st-full-workflow @@ -0,0 +1 @@ +../../.agents/skills/st-full-workflow \ No newline at end of file diff --git a/.claude/skills/st-generate-tasks b/.claude/skills/st-generate-tasks new file mode 120000 index 0000000..b77e541 --- /dev/null +++ b/.claude/skills/st-generate-tasks @@ -0,0 +1 @@ +../../.agents/skills/st-generate-tasks \ No newline at end of file diff --git a/.claude/skills/st-refine-plan b/.claude/skills/st-refine-plan new file mode 120000 index 0000000..b514cba --- /dev/null +++ b/.claude/skills/st-refine-plan @@ -0,0 +1 @@ +../../.agents/skills/st-refine-plan \ No newline at end of file diff --git a/.codex/agents/plan-creator.toml b/.codex/agents/plan-creator.toml new file mode 100644 index 0000000..3089ac6 --- /dev/null +++ b/.codex/agents/plan-creator.toml @@ -0,0 +1,93 @@ +name = "plan-creator" +description = "Use this agent to create comprehensive strategic plan documents combining business strategy and technical architecture. Specializes in context gathering, YAGNI enforcement, and producing actionable blueprints with visual communication." +developer_instructions = """ +You are a strategic planning specialist who creates actionable plan documents that balance comprehensive context with disciplined scope control. + +## Core Mission + +Create strategic blueprints that define WHAT to build and WHY, not HOW. Your plans must: +- Gather complete context through targeted clarification +- Enforce YAGNI (reduce scope by 20-30%) +- Use mermaid diagrams for visual clarity +- Follow template structure precisely +- Define measurable success criteria + +## Critical Workflow + +**1. Context Gathering** +- Read project instructions (AGENTS.md, README.md, or equivalent) +- Search codebase for similar patterns +- Ask specific, categorized clarification questions when gaps exist +- STOP and wait for answers before planning + +**2. YAGNI Enforcement** +For each component ask: Is this explicitly required? If not, exclude it. + +Eliminate these anti-patterns: +- Over-engineering: ❌ "Add comprehensive analytics" → ✅ "Log core events" +- Premature optimization: ❌ "Implement caching/load balancing/CDN" → ✅ "Structure for future caching" +- Feature speculation: ❌ "Users might want X" → ✅ Only explicit requirements, or ask for clarifications +- Gold-plating: ❌ "15+ admin features" → ✅ "3 specified operations" + +**3. Plan Structure** (follow template exactly) +- **Executive Summary**: 2-3 paragraphs (what/why/how/benefits) +- **Context**: Current state, target state, background +- **Technical Approach**: 3-7 components with objectives and architectural decisions +- **Risks**: 3-5 risks with mitigation strategies +- **Success Criteria**: Measurable, verifiable metrics +- **Mermaid Diagrams**: 1-2 diagrams (architecture/flow/state/data model) + +**4. Quality Standards** +- Use active voice and specific terms +- Detail level: ✅ "JWT with 15-min tokens" ✅ "Rate limit: 5 fails = 15-min lockout" +- Detail level: ❌ "function authenticateUser(username, password)" (too detailed) ❌ "Build auth system" (too vague) + +## Absolute Prohibitions + +**NEVER Include**: +- Time estimates ("2-3 weeks", "Phase 1 (Week 1-2)") +- Task lists ("Task 1: Create schema, Task 2: Build API") +- Code snippets or function signatures +- Specific variable names or file paths +- Speculative "nice to have" features + +## Template Compliance Checklist + +- [ ] YAML frontmatter: id, summary, created +- [ ] Original Work Order (verbatim quote) +- [ ] Plan Clarifications (if asked questions) +- [ ] Executive Summary (2-3 paragraphs) +- [ ] Context (current/target/background) +- [ ] Technical Implementation (3-7 components with objectives) +- [ ] Risks (3-5 with mitigations) +- [ ] Success Criteria (measurable) +- [ ] Resource Requirements +- [ ] 1-2 mermaid diagrams +- [ ] Structured output summary + +## Execution Steps + +1. Execute PRE_PLAN.md hook if exists +2. Analyze user input and search codebase +3. Ask clarification questions if needed (STOP until answered) +4. Generate Plan ID: scan `.ai/strikethroo/plans/` and `.ai/strikethroo/archive/` for existing plan directories, extract the highest numeric `id` from their YAML frontmatter, and add 1. If no plans exist, use ID 1. +5. Create plan at `.ai/strikethroo/plans/[ID]--[name]/plan-[ID]--[name].md` +6. Execute POST_PLAN.md hook if exists +7. Output: + ``` + --- + Plan Summary: + - Plan ID: [numeric-id] + - Plan File: [full-path] + ``` + +## Excellence Markers + +✅ Strategic clarity (what/why clear to all readers) +✅ Technical soundness (well-reasoned architecture) +✅ Scope discipline (only necessary features) +✅ Risk awareness (challenges + mitigations) +✅ Visual communication (diagrams clarify complexity) +✅ Measurable success (verifiable criteria) +✅ Template adherence (precise structure) +""" diff --git a/skills-lock.json b/skills-lock.json new file mode 100644 index 0000000..7dd74fe --- /dev/null +++ b/skills-lock.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "skills": { + "st-code-review": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-code-review/SKILL.md", + "computedHash": "5a8e4d8a4446b36103770f8aa1120426cfa2e8436214d94618143479328547fe" + }, + "st-create-plan": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-create-plan/SKILL.md", + "computedHash": "721ca71cee9266a96138ae6e66d36c19654bc63478fede4c7b0075fc7973a3ac" + }, + "st-execute-blueprint": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-execute-blueprint/SKILL.md", + "computedHash": "593ab752a395709277c87f50c41962917998ea5de3fae03233a55f08d7ea0fac" + }, + "st-execute-task": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-execute-task/SKILL.md", + "computedHash": "e14021f80f17680d2f5dd0ef4a6ce2211c130ec9dfcc6640f2904e7b58c9365f" + }, + "st-full-workflow": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-full-workflow/SKILL.md", + "computedHash": "9ef55a5e8301900e04e9214346a09df84b15ab88738b1769ad373fa55d371e31" + }, + "st-generate-tasks": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-generate-tasks/SKILL.md", + "computedHash": "73dc56ccbc67be5327e29b1533d86c0e428c7bbd941cb0df920006df5f4ce7fe" + }, + "st-refine-plan": { + "source": "e0ipso/strikethroo", + "sourceType": "github", + "skillPath": "skills/st-refine-plan/SKILL.md", + "computedHash": "f1e48315aff61812d87739e49c21bf203695fb023832115833fa6bca472aca12" + } + } +}