{"owner":"mangiucugna","repo":"json_repair","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":1880,"categories":["root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".agents/skills/docs-demo-local-test/SKILL.md",".agents/skills/docs-demo-local-test/agents/openai.yaml"],"skills":{"AGENTS.md":"# Repo Notes for Codex\n\n## Environment\n- Use the uv-managed environment at `.venv`; install dev dependencies with `uv sync --group dev`.\n- Prefer `uv run ...` for Python tooling.\n- Dependency groups live in `pyproject.toml`; update `uv.lock` when dependencies change.\n\n## Validation\n- Run the full test suite with `uv run pytest`.\n- Run the full hook stack with `pre-commit run --all-files`.\n- The hook stack may rewrite `uv.lock` or `.pre-commit-config.yaml`; if hook-managed files change during commit flows, restage the resulting updates instead of repeatedly restoring them.\n- Keep CI's direct `ruff format` invocation aligned with the Python-only `ruff-format` pre-commit hook; Markdown is globally excluded because documentation code examples are not formatter input.\n\n## Release And Packaging\n- Project version lives in `pyproject.toml` under `[project].version`; use semantic versioning, with patch bumps for bug fixes.\n- Keep `CITATION.cff` aligned with the released version metadata in `pyproject.toml`.\n- Keep `MANIFEST.in` pruning `tests` so test modules are not shipped in the sdist.\n- In `[tool.setuptools.package-data]`, use the real package key `json_repair` so `py.typed` remains included.\n- Run `uvx twine check dist/*` after building and before publishing.\n\n## Docs\n- Keep `README.zh.md` aligned with `README.md` when behavior or contributor guidance changes.\n- `README.md` is the PyPI long description via `pyproject.toml`; avoid relative file or image links there.\n- Keep docs demo share state in the URL hash, not query params.\n\n## Durable Implementation Notes\n- Keep valid-JSON fast paths on the standard library path; `strict=True` must not second-guess inputs that `json.loads` already accepts.\n- Treat `skip_json_loads=True` as an explicit opt-out for inputs already known to be invalid; do not assume behavior must match the stdlib-preserving path for valid JSON.\n- `load(fd)` should behave like `json.load(fd)` and repair from the descriptor's current position.\n- When adding repair heuristics, keep `strict=True` conservative and emit parser logs for automatic corrections.\n- When a schema is provided, apply schema repair and validation for both valid and invalid JSON inputs.\n- For top-level Pydantic model fields with simple string aliases, preserve field-name keys during schema-guided parsing when the model accepts them, even when `additionalProperties` is false; canonicalize after parsing so explicit aliases retain precedence.\n- Keep schema-guided dispatch centralized in `JSONParser.parse_json(schema, path)`.\n- `patternProperties` matching is intentionally limited to a safe subset; do not execute user-supplied regexes.\n- Preserve schema dict identity in `SchemaRepairer.resolve_schema` whenever possible so validator caching remains effective.\n- When validating a detached `anyOf` or `oneOf` branch, retain the original root schema's resolver scope so root-relative `$ref` values can resolve `$defs`.\n- `schema_repair_mode` supports only `standard` and opt-in `salvage`; salvage may recover strongly evidenced structural mismatches, but must not silently coerce or infer semantic property renames (for example, `results` to `patterns`).\n- For sequential top-level fragments, salvage may skip candidates that fail schema repair or validation and return the first schema-valid fragment; never select an item from an actual top-level JSON array.\n- Treat user-supplied schemas as an attacker-controlled input surface: deep nesting in schema normalization, validation, and repair paths needs an explicit depth limit or controlled `ValueError`, not an uncaught `RecursionError`.\n\n## Refactor Pitfalls\n- In `repair_json`, keep a single shared output-finalization path for logging, `return_objects`, empty-string handling, and `json.dumps`.\n- Parser refactors are sensitive to context lifetimes and heuristic branch ordering; preserve malformed-input behavior when restructuring `parse_string` or `parse_object`.\n- Recognize unquoted literals only as complete tokens followed by a JSON separator or end-of-input; support case-insensitive `none` as null, but keep quoted values and other barewords as strings.\n- Treat comma-separated parenthesized sequences as Python-style tuples that normalize to arrays, while preserving a single parenthesized value as a scalar; Python-style literals are supported only within arrays, objects, and tuples, not as bare top-level values.\n- Preserve bare quotes inside compact regex character classes such as `['\"]` and `[^'\"]`; do not let them split the enclosing JSON value into separate top-level elements.\n- For an object value beginning with a doubled quote, retain the second quote only when non-whitespace inner content and a distinct valid outer terminator evidence a quoted span; preserve ordinary redundant-leading-quote and doubled-ending normalization.\n- When an object property contains an unclosed array of scalar values followed by a quoted `key: value` member, close the array and resume the enclosing object; preserve direct-array and pre-scalar missing-object recovery (`[\"key\": \"value\"] -> [{\"key\": \"value\"}]`).\n- Top-level raw decoding may discard a valid prefix only when non-comma garbage follows; preserve complete-input heuristics and defer comma-prefixed continuations to structural object repair.\n- Probe a missing opening object brace at most once per input, only in the final dispatch fallback for an initial quoted key followed by a colon and a final `}` ignoring trailing whitespace, and accept only when one insertion makes the entire input a valid object; limit the decoder remainder check to JSON whitespace, log the correction, and reject it in strict mode.\n- Performance regressions often hide in repeated `parse_string` lookahead scans on long malformed object values; include cases with many commas or `}` characters before a far quote, and retain only inputs with a meaningful baseline slowdown (roughly one second or more).\n- In `parse_number`, a `+` is valid only immediately after an exponent marker (`e`/`E`); do not broaden plus handling for unrelated malformed arithmetic-like tokens.\n- Normalize top-level `RecursionError` into `ValueError`.\n",".agents/skills/docs-demo-local-test/SKILL.md":"---\nname: docs-demo-local-test\ndescription: Test the docs JSON repair demo against local backend changes before publishing. Use this when modifying docs/app.py or docs UI files and you need local end-to-end verification.\n---\n\n# Docs Demo Local Test\n\n## Overview\n\nUse this workflow to validate docs demo behavior with local code only, without relying on the deployed PythonAnywhere API. This is the default verification path for `docs/app.py`, `docs/index.js`, `docs/index.html`, `docs/index.zh.html`, and `docs/styles.css` changes.\n\n## Workflow\n\n1. Start the local demo API server:\n```bash\nUV_CACHE_DIR=/tmp/uv-cache uv run --with flask --with flask-cors python docs/app.py\n```\n2. Start the local static site server:\n```bash\npython3 -m http.server 4173 --directory docs\n```\n3. Open `http://127.0.0.1:4173/index.html`.\n4. In browser devtools, patch `fetch` so the page hits local API instead of PythonAnywhere:\n```javascript\n() => {\n  const target = \"https://mangiucugna.pythonanywhere.com/api/repair-json\";\n  const local = \"http://127.0.0.1:5000/api/repair-json\";\n  const originalFetch = window.fetch.bind(window);\n  window.fetch = (input, init) => {\n    let nextInput = input;\n    if (typeof input === \"string\" && input === target) {\n      nextInput = local;\n    } else if (input instanceof Request && input.url === target) {\n      nextInput = new Request(local, input);\n    }\n    return originalFetch(nextInput, init);\n  };\n  return \"fetch patched\";\n}\n```\n5. Run a schema coercion check:\n- Input JSON: `{\"value\":\"1\",}`\n- Schema: `{\"type\":\"object\",\"properties\":{\"value\":{\"type\":\"integer\"}},\"required\":[\"value\"]}`\n- Expected output JSON: `{\"value\": 1}`\n- Expected log contains: `Coerced string to integer`\n6. Confirm network request target is local:\n- `POST http://127.0.0.1:5000/api/repair-json`\n7. Capture screenshot if needed.\n8. Stop both local servers with `Ctrl+C`.\n\n## Troubleshooting\n\n- If `uv run` fails with cache permission errors, rerun with `UV_CACHE_DIR=/tmp/uv-cache`.\n- If Flask modules are missing, keep using `uv run --with flask --with flask-cors ...`.\n- If output still matches production behavior, the fetch patch did not apply; reload and patch again before typing input.\n",".agents/skills/docs-demo-local-test/agents/openai.yaml":"interface:\n  display_name: \"Docs Demo Local Test\"\n  short_description: \"Validate docs demo locally before deploys\"\n  default_prompt: \"Run local docs demo API+UI and verify schema behavior against local code.\"\n"},"files":{"AGENTS.md":"# Repo Notes for Codex\n\n## Environment\n- Use the uv-managed environment at `.venv`; install dev dependencies with `uv sync --group dev`.\n- Prefer `uv run ...` for Python tooling.\n- Dependency groups live in `pyproject.toml`; update `uv.lock` when dependencies change.\n\n## Validation\n- Run the full test suite with `uv run pytest`.\n- Run the full hook stack with `pre-commit run --all-files`.\n- The hook stack may rewrite `uv.lock` or `.pre-commit-config.yaml`; if hook-managed files change during commit flows, restage the resulting updates instead of repeatedly restoring them.\n- Keep CI's direct `ruff format` invocation aligned with the Python-only `ruff-format` pre-commit hook; Markdown is globally excluded because documentation code examples are not formatter input.\n\n## Release And Packaging\n- Project version lives in `pyproject.toml` under `[project].version`; use semantic versioning, with patch bumps for bug fixes.\n- Keep `CITATION.cff` aligned with the released version metadata in `pyproject.toml`.\n- Keep `MANIFEST.in` pruning `tests` so test modules are not shipped in the sdist.\n- In `[tool.setuptools.package-data]`, use the real package key `json_repair` so `py.typed` remains included.\n- Run `uvx twine check dist/*` after building and before publishing.\n\n## Docs\n- Keep `README.zh.md` aligned with `README.md` when behavior or contributor guidance changes.\n- `README.md` is the PyPI long description via `pyproject.toml`; avoid relative file or image links there.\n- Keep docs demo share state in the URL hash, not query params.\n\n## Durable Implementation Notes\n- Keep valid-JSON fast paths on the standard library path; `strict=True` must not second-guess inputs that `json.loads` already accepts.\n- Treat `skip_json_loads=True` as an explicit opt-out for inputs already known to be invalid; do not assume behavior must match the stdlib-preserving path for valid JSON.\n- `load(fd)` should behave like `json.load(fd)` and repair from the descriptor's current position.\n- When adding repair heuristics, keep `strict=True` conservative and emit parser logs for automatic corrections.\n- When a schema is provided, apply schema repair and validation for both valid and invalid JSON inputs.\n- For top-level Pydantic model fields with simple string aliases, preserve field-name keys during schema-guided parsing when the model accepts them, even when `additionalProperties` is false; canonicalize after parsing so explicit aliases retain precedence.\n- Keep schema-guided dispatch centralized in `JSONParser.parse_json(schema, path)`.\n- `patternProperties` matching is intentionally limited to a safe subset; do not execute user-supplied regexes.\n- Preserve schema dict identity in `SchemaRepairer.resolve_schema` whenever possible so validator caching remains effective.\n- When validating a detached `anyOf` or `oneOf` branch, retain the original root schema's resolver scope so root-relative `$ref` values can resolve `$defs`.\n- `schema_repair_mode` supports only `standard` and opt-in `salvage`; salvage may recover strongly evidenced structural mismatches, but must not silently coerce or infer semantic property renames (for example, `results` to `patterns`).\n- For sequential top-level fragments, salvage may skip candidates that fail schema repair or validation and return the first schema-valid fragment; never select an item from an actual top-level JSON array.\n- Treat user-supplied schemas as an attacker-controlled input surface: deep nesting in schema normalization, validation, and repair paths needs an explicit depth limit or controlled `ValueError`, not an uncaught `RecursionError`.\n\n## Refactor Pitfalls\n- In `repair_json`, keep a single shared output-finalization path for logging, `return_objects`, empty-string handling, and `json.dumps`.\n- Parser refactors are sensitive to context lifetimes and heuristic branch ordering; preserve malformed-input behavior when restructuring `parse_string` or `parse_object`.\n- Recognize unquoted literals only as complete tokens followed by a JSON separator or end-of-input; support case-insensitive `none` as null, but keep quoted values and other barewords as strings.\n- Treat comma-separated parenthesized sequences as Python-style tuples that normalize to arrays, while preserving a single parenthesized value as a scalar; Python-style literals are supported only within arrays, objects, and tuples, not as bare top-level values.\n- Preserve bare quotes inside compact regex character classes such as `['\"]` and `[^'\"]`; do not let them split the enclosing JSON value into separate top-level elements.\n- For an object value beginning with a doubled quote, retain the second quote only when non-whitespace inner content and a distinct valid outer terminator evidence a quoted span; preserve ordinary redundant-leading-quote and doubled-ending normalization.\n- When an object property contains an unclosed array of scalar values followed by a quoted `key: value` member, close the array and resume the enclosing object; preserve direct-array and pre-scalar missing-object recovery (`[\"key\": \"value\"] -> [{\"key\": \"value\"}]`).\n- Top-level raw decoding may discard a valid prefix only when non-comma garbage follows; preserve complete-input heuristics and defer comma-prefixed continuations to structural object repair.\n- Probe a missing opening object brace at most once per input, only in the final dispatch fallback for an initial quoted key followed by a colon and a final `}` ignoring trailing whitespace, and accept only when one insertion makes the entire input a valid object; limit the decoder remainder check to JSON whitespace, log the correction, and reject it in strict mode.\n- Performance regressions often hide in repeated `parse_string` lookahead scans on long malformed object values; include cases with many commas or `}` characters before a far quote, and retain only inputs with a meaningful baseline slowdown (roughly one second or more).\n- In `parse_number`, a `+` is valid only immediately after an exponent marker (`e`/`E`); do not broaden plus handling for unrelated malformed arithmetic-like tokens.\n- Normalize top-level `RecursionError` into `ValueError`.\n",".agents/skills/docs-demo-local-test/SKILL.md":"---\nname: docs-demo-local-test\ndescription: Test the docs JSON repair demo against local backend changes before publishing. Use this when modifying docs/app.py or docs UI files and you need local end-to-end verification.\n---\n\n# Docs Demo Local Test\n\n## Overview\n\nUse this workflow to validate docs demo behavior with local code only, without relying on the deployed PythonAnywhere API. This is the default verification path for `docs/app.py`, `docs/index.js`, `docs/index.html`, `docs/index.zh.html`, and `docs/styles.css` changes.\n\n## Workflow\n\n1. Start the local demo API server:\n```bash\nUV_CACHE_DIR=/tmp/uv-cache uv run --with flask --with flask-cors python docs/app.py\n```\n2. Start the local static site server:\n```bash\npython3 -m http.server 4173 --directory docs\n```\n3. Open `http://127.0.0.1:4173/index.html`.\n4. In browser devtools, patch `fetch` so the page hits local API instead of PythonAnywhere:\n```javascript\n() => {\n  const target = \"https://mangiucugna.pythonanywhere.com/api/repair-json\";\n  const local = \"http://127.0.0.1:5000/api/repair-json\";\n  const originalFetch = window.fetch.bind(window);\n  window.fetch = (input, init) => {\n    let nextInput = input;\n    if (typeof input === \"string\" && input === target) {\n      nextInput = local;\n    } else if (input instanceof Request && input.url === target) {\n      nextInput = new Request(local, input);\n    }\n    return originalFetch(nextInput, init);\n  };\n  return \"fetch patched\";\n}\n```\n5. Run a schema coercion check:\n- Input JSON: `{\"value\":\"1\",}`\n- Schema: `{\"type\":\"object\",\"properties\":{\"value\":{\"type\":\"integer\"}},\"required\":[\"value\"]}`\n- Expected output JSON: `{\"value\": 1}`\n- Expected log contains: `Coerced string to integer`\n6. Confirm network request target is local:\n- `POST http://127.0.0.1:5000/api/repair-json`\n7. Capture screenshot if needed.\n8. Stop both local servers with `Ctrl+C`.\n\n## Troubleshooting\n\n- If `uv run` fails with cache permission errors, rerun with `UV_CACHE_DIR=/tmp/uv-cache`.\n- If Flask modules are missing, keep using `uv run --with flask --with flask-cors ...`.\n- If output still matches production behavior, the fetch patch did not apply; reload and patch again before typing input.\n",".agents/skills/docs-demo-local-test/agents/openai.yaml":"interface:\n  display_name: \"Docs Demo Local Test\"\n  short_description: \"Validate docs demo locally before deploys\"\n  default_prompt: \"Run local docs demo API+UI and verify schema behavior against local code.\"\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/mangiucugna/json_repair/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Repo Notes for Codex\n\n## Environment\n- Use the uv-managed environment at `.venv`; install dev dependencies with `uv sync --group dev`.\n- Prefer `uv run ...` for Python tooling.\n- Dependency groups live in `pyproject.toml`; update `uv.lock` when dependencies change.\n\n## Validation\n- Run the full test suite with `uv run pytest`.\n- Run the full hook stack with `pre-commit run --all-files`.\n- The hook stack may rewrite `uv.lock` or `.pre-commit-config.yaml`; if hook-managed files change during commit flows, restage the resulting updates instead of repeatedly restoring them.\n- Keep CI's direct `ruff format` invocation aligned with the Python-only `ruff-format` pre-commit hook; Markdown is globally excluded because documentation code examples are not formatter input.\n\n## Release And Packaging\n- Project version lives in `pyproject.toml` under `[project].version`; use semantic versioning, with patch bumps for bug fixes.\n- Keep `CITATION.cff` aligned with the released version metadata in `pyproject.toml`.\n- Keep `MANIFEST.in` pruning `tests` so test modules are not shipped in the sdist.\n- In `[tool.setuptools.package-data]`, use the real package key `json_repair` so `py.typed` remains included.\n- Run `uvx twine check dist/*` after building and before publishing.\n\n## Docs\n- Keep `README.zh.md` aligned with `README.md` when behavior or contributor guidance changes.\n- `README.md` is the PyPI long description via `pyproject.toml`; avoid relative file or image links there.\n- Keep docs demo share state in the URL hash, not query params.\n\n## Durable Implementation Notes\n- Keep valid-JSON fast paths on the standard library path; `strict=True` must not second-guess inputs that `json.loads` already accepts.\n- Treat `skip_json_loads=True` as an explicit opt-out for inputs already known to be invalid; do not assume behavior must match the stdlib-preserving path for valid JSON.\n- `load(fd)` should behave like `json.load(fd)` and repair from the descriptor's current position.\n- When adding repair heuristics, keep `strict=True` conservative and emit parser logs for automatic corrections.\n- When a schema is provided, apply schema repair and validation for both valid and invalid JSON inputs.\n- For top-level Pydantic model fields with simple string aliases, preserve field-name keys during schema-guided parsing when the model accepts them, even when `additionalProperties` is false; canonicalize after parsing so explicit aliases retain precedence.\n- Keep schema-guided dispatch centralized in `JSONParser.parse_json(schema, path)`.\n- `patternProperties` matching is intentionally limited to a safe subset; do not execute user-supplied regexes.\n- Preserve schema dict identity in `SchemaRepairer.resolve_schema` whenever possible so validator caching remains effective.\n- When validating a detached `anyOf` or `oneOf` branch, retain the original root schema's resolver scope so root-relative `$ref` values can resolve `$defs`.\n- `schema_repair_mode` supports only `standard` and opt-in `salvage`; salvage may recover strongly evidenced structural mismatches, but must not silently coerce or infer semantic property renames (for example, `results` to `patterns`).\n- For sequential top-level fragments, salvage may skip candidates that fail schema repair or validation and return the first schema-valid fragment; never select an item from an actual top-level JSON array.\n- Treat user-supplied schemas as an attacker-controlled input surface: deep nesting in schema normalization, validation, and repair paths needs an explicit depth limit or controlled `ValueError`, not an uncaught `RecursionError`.\n\n## Refactor Pitfalls\n- In `repair_json`, keep a single shared output-finalization path for logging, `return_objects`, empty-string handling, and `json.dumps`.\n- Parser refactors are sensitive to context lifetimes and heuristic branch ordering; preserve malformed-input behavior when restructuring `parse_string` or `parse_object`.\n- Recognize unquoted literals only as complete tokens followed by a JSON separator or end-of-input; support case-insensitive `none` as null, but keep quoted values and other barewords as strings.\n- Treat comma-separated parenthesized sequences as Python-style tuples that normalize to arrays, while preserving a single parenthesized value as a scalar; Python-style literals are supported only within arrays, objects, and tuples, not as bare top-level values.\n- Preserve bare quotes inside compact regex character classes such as `['\"]` and `[^'\"]`; do not let them split the enclosing JSON value into separate top-level elements.\n- For an object value beginning with a doubled quote, retain the second quote only when non-whitespace inner content and a distinct valid outer terminator evidence a quoted span; preserve ordinary redundant-leading-quote and doubled-ending normalization.\n- When an object property contains an unclosed array of scalar values followed by a quoted `key: value` member, close the array and resume the enclosing object; preserve direct-array and pre-scalar missing-object recovery (`[\"key\": \"value\"] -> [{\"key\": \"value\"}]`).\n- Top-level raw decoding may discard a valid prefix only when non-comma garbage follows; preserve complete-input heuristics and defer comma-prefixed continuations to structural object repair.\n- Probe a missing opening object brace at most once per input, only in the final dispatch fallback for an initial quoted key followed by a colon and a final `}` ignoring trailing whitespace, and accept only when one insertion makes the entire input a valid object; limit the decoder remainder check to JSON whitespace, log the correction, and reject it in strict mode.\n- Performance regressions often hide in repeated `parse_string` lookahead scans on long malformed object values; include cases with many commas or `}` characters before a far quote, and retain only inputs with a meaningful baseline slowdown (roughly one second or more).\n- In `parse_number`, a `+` is valid only immediately after an exponent marker (`e`/`E`); do not broaden plus handling for unrelated malformed arithmetic-like tokens.\n- Normalize top-level `RecursionError` into `ValueError`.\n","isInternal":false,"tokens":1282,"sizeBytes":6154},{"name":"openai.yaml","path":".agents/skills/docs-demo-local-test/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/mangiucugna/json_repair/HEAD/.agents/skills/docs-demo-local-test/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"interface:\n  display_name: \"Docs Demo Local Test\"\n  short_description: \"Validate docs demo locally before deploys\"\n  default_prompt: \"Run local docs demo API+UI and verify schema behavior against local code.\"\n","isInternal":false,"tokens":45,"sizeBytes":209},{"name":"SKILL.md","path":".agents/skills/docs-demo-local-test/SKILL.md","rawUrl":"https://raw.githubusercontent.com/mangiucugna/json_repair/HEAD/.agents/skills/docs-demo-local-test/SKILL.md","title":"docs-demo-local-test","category":"anthropic-skill","format":"markdown","content":"---\nname: docs-demo-local-test\ndescription: Test the docs JSON repair demo against local backend changes before publishing. Use this when modifying docs/app.py or docs UI files and you need local end-to-end verification.\n---\n\n# Docs Demo Local Test\n\n## Overview\n\nUse this workflow to validate docs demo behavior with local code only, without relying on the deployed PythonAnywhere API. This is the default verification path for `docs/app.py`, `docs/index.js`, `docs/index.html`, `docs/index.zh.html`, and `docs/styles.css` changes.\n\n## Workflow\n\n1. Start the local demo API server:\n```bash\nUV_CACHE_DIR=/tmp/uv-cache uv run --with flask --with flask-cors python docs/app.py\n```\n2. Start the local static site server:\n```bash\npython3 -m http.server 4173 --directory docs\n```\n3. Open `http://127.0.0.1:4173/index.html`.\n4. In browser devtools, patch `fetch` so the page hits local API instead of PythonAnywhere:\n```javascript\n() => {\n  const target = \"https://mangiucugna.pythonanywhere.com/api/repair-json\";\n  const local = \"http://127.0.0.1:5000/api/repair-json\";\n  const originalFetch = window.fetch.bind(window);\n  window.fetch = (input, init) => {\n    let nextInput = input;\n    if (typeof input === \"string\" && input === target) {\n      nextInput = local;\n    } else if (input instanceof Request && input.url === target) {\n      nextInput = new Request(local, input);\n    }\n    return originalFetch(nextInput, init);\n  };\n  return \"fetch patched\";\n}\n```\n5. Run a schema coercion check:\n- Input JSON: `{\"value\":\"1\",}`\n- Schema: `{\"type\":\"object\",\"properties\":{\"value\":{\"type\":\"integer\"}},\"required\":[\"value\"]}`\n- Expected output JSON: `{\"value\": 1}`\n- Expected log contains: `Coerced string to integer`\n6. Confirm network request target is local:\n- `POST http://127.0.0.1:5000/api/repair-json`\n7. Capture screenshot if needed.\n8. Stop both local servers with `Ctrl+C`.\n\n## Troubleshooting\n\n- If `uv run` fails with cache permission errors, rerun with `UV_CACHE_DIR=/tmp/uv-cache`.\n- If Flask modules are missing, keep using `uv run --with flask --with flask-cors ...`.\n- If output still matches production behavior, the fetch patch did not apply; reload and patch again before typing input.\n","frontmatter":{"name":"docs-demo-local-test","description":"Test the docs JSON repair demo against local backend changes before publishing. Use this when modifying docs/app.py or docs UI files and you need local end-to-end verification."},"isInternal":false,"tokens":553,"sizeBytes":2194}],"systemPromptSnippet":"<yakaai_skills repo=\"mangiucugna/json_repair\">\n<!-- File: AGENTS.md (Tokens: ~1282 | Category: root-instruction) -->\n# Repo Notes for Codex\n\n## Environment\n- Use the uv-managed environment at `.venv`; install dev dependencies with `uv sync --group dev`.\n- Prefer `uv run ...` for Python tooling.\n- Dependency groups live in `pyproject.toml`; update `uv.lock` when dependencies change.\n\n## Validation\n- Run the full test suite with `uv run pytest`.\n- Run the full hook stack with `pre-commit run --all-files`.\n- The hook stack may rewrite `uv.lock` or `.pre-commit-config.yaml`; if hook-managed files change during commit flows, restage the resulting updates instead of repeatedly restoring them.\n- Keep CI's direct `ruff format` invocation aligned with the Python-only `ruff-format` pre-commit hook; Markdown is globally excluded because documentation code examples are not formatter input.\n\n## Release And Packaging\n- Project version lives in `pyproject.toml` under `[project].version`; use semantic versioning, with patch bumps for bug fixes.\n- Keep `CITATION.cff` aligned with the released version metadata in `pyproject.toml`.\n- Keep `MANIFEST.in` pruning `tests` so test modules are not shipped in the sdist.\n- In `[tool.setuptools.package-data]`, use the real package key `json_repair` so `py.typed` remains included.\n- Run `uvx twine check dist/*` after building and before publishing.\n\n## Docs\n- Keep `README.zh.md` aligned with `README.md` when behavior or contributor guidance changes.\n- `README.md` is the PyPI long description via `pyproject.toml`; avoid relative file or image links there.\n- Keep docs demo share state in the URL hash, not query params.\n\n## Durable Implementation Notes\n- Keep valid-JSON fast paths on the standard library path; `strict=True` must not second-guess inputs that `json.loads` already accepts.\n- Treat `skip_json_loads=True` as an explicit opt-out for inputs already known to be invalid; do not assume behavior must match the stdlib-preserving path for valid JSON.\n- `load(fd)` should behave like `json.load(fd)` and repair from the descriptor's current position.\n- When adding repair heuristics, keep `strict=True` conservative and emit parser logs for automatic corrections.\n- When a schema is provided, apply schema repair and validation for both valid and invalid JSON inputs.\n- For top-level Pydantic model fields with simple string aliases, preserve field-name keys during schema-guided parsing when the model accepts them, even when `additionalProperties` is false; canonicalize after parsing so explicit aliases retain precedence.\n- Keep schema-guided dispatch centralized in `JSONParser.parse_json(schema, path)`.\n- `patternProperties` matching is intentionally limited to a safe subset; do not execute user-supplied regexes.\n- Preserve schema dict identity in `SchemaRepairer.resolve_schema` whenever possible so validator caching remains effective.\n- When validating a detached `anyOf` or `oneOf` branch, retain the original root schema's resolver scope so root-relative `$ref` values can resolve `$defs`.\n- `schema_repair_mode` supports only `standard` and opt-in `salvage`; salvage may recover strongly evidenced structural mismatches, but must not silently coerce or infer semantic property renames (for example, `results` to `patterns`).\n- For sequential top-level fragments, salvage may skip candidates that fail schema repair or validation and return the first schema-valid fragment; never select an item from an actual top-level JSON array.\n- Treat user-supplied schemas as an attacker-controlled input surface: deep nesting in schema normalization, validation, and repair paths needs an explicit depth limit or controlled `ValueError`, not an uncaught `RecursionError`.\n\n## Refactor Pitfalls\n- In `repair_json`, keep a single shared output-finalization path for logging, `return_objects`, empty-string handling, and `json.dumps`.\n- Parser refactors are sensitive to context lifetimes and heuristic branch ordering; preserve malformed-input behavior when restructuring `parse_string` or `parse_object`.\n- Recognize unquoted literals only as complete tokens followed by a JSON separator or end-of-input; support case-insensitive `none` as null, but keep quoted values and other barewords as strings.\n- Treat comma-separated parenthesized sequences as Python-style tuples that normalize to arrays, while preserving a single parenthesized value as a scalar; Python-style literals are supported only within arrays, objects, and tuples, not as bare top-level values.\n- Preserve bare quotes inside compact regex character classes such as `['\"]` and `[^'\"]`; do not let them split the enclosing JSON value into separate top-level elements.\n- For an object value beginning with a doubled quote, retain the second quote only when non-whitespace inner content and a distinct valid outer terminator evidence a quoted span; preserve ordinary redundant-leading-quote and doubled-ending normalization.\n- When an object property contains an unclosed array of scalar values followed by a quoted `key: value` member, close the array and resume the enclosing object; preserve direct-array and pre-scalar missing-object recovery (`[\"key\": \"value\"] -> [{\"key\": \"value\"}]`).\n- Top-level raw decoding may discard a valid prefix only when non-comma garbage follows; preserve complete-input heuristics and defer comma-prefixed continuations to structural object repair.\n- Probe a missing opening object brace at most once per input, only in the final dispatch fallback for an initial quoted key followed by a colon and a final `}` ignoring trailing whitespace, and accept only when one insertion makes the entire input a valid object; limit the decoder remainder check to JSON whitespace, log the correction, and reject it in strict mode.\n- Performance regressions often hide in repeated `parse_string` lookahead scans on long malformed object values; include cases with many commas or `}` characters before a far quote, and retain only inputs with a meaningful baseline slowdown (roughly one second or more).\n- In `parse_number`, a `+` is valid only immediately after an exponent marker (`e`/`E`); do not broaden plus handling for unrelated malformed arithmetic-like tokens.\n- Normalize top-level `RecursionError` into `ValueError`.\n\n<!-- File: .agents/skills/docs-demo-local-test/agents/openai.yaml (Tokens: ~45 | Category: anthropic-skill) -->\ninterface:\n  display_name: \"Docs Demo Local Test\"\n  short_description: \"Validate docs demo locally before deploys\"\n  default_prompt: \"Run local docs demo API+UI and verify schema behavior against local code.\"\n\n<!-- File: .agents/skills/docs-demo-local-test/SKILL.md (Tokens: ~553 | Category: anthropic-skill) -->\n---\nname: docs-demo-local-test\ndescription: Test the docs JSON repair demo against local backend changes before publishing. Use this when modifying docs/app.py or docs UI files and you need local end-to-end verification.\n---\n\n# Docs Demo Local Test\n\n## Overview\n\nUse this workflow to validate docs demo behavior with local code only, without relying on the deployed PythonAnywhere API. This is the default verification path for `docs/app.py`, `docs/index.js`, `docs/index.html`, `docs/index.zh.html`, and `docs/styles.css` changes.\n\n## Workflow\n\n1. Start the local demo API server:\n```bash\nUV_CACHE_DIR=/tmp/uv-cache uv run --with flask --with flask-cors python docs/app.py\n```\n2. Start the local static site server:\n```bash\npython3 -m http.server 4173 --directory docs\n```\n3. Open `http://127.0.0.1:4173/index.html`.\n4. In browser devtools, patch `fetch` so the page hits local API instead of PythonAnywhere:\n```javascript\n() => {\n  const target = \"https://mangiucugna.pythonanywhere.com/api/repair-json\";\n  const local = \"http://127.0.0.1:5000/api/repair-json\";\n  const originalFetch = window.fetch.bind(window);\n  window.fetch = (input, init) => {\n    let nextInput = input;\n    if (typeof input === \"string\" && input === target) {\n      nextInput = local;\n    } else if (input instanceof Request && input.url === target) {\n      nextInput = new Request(local, input);\n    }\n    return originalFetch(nextInput, init);\n  };\n  return \"fetch patched\";\n}\n```\n5. Run a schema coercion check:\n- Input JSON: `{\"value\":\"1\",}`\n- Schema: `{\"type\":\"object\",\"properties\":{\"value\":{\"type\":\"integer\"}},\"required\":[\"value\"]}`\n- Expected output JSON: `{\"value\": 1}`\n- Expected log contains: `Coerced string to integer`\n6. Confirm network request target is local:\n- `POST http://127.0.0.1:5000/api/repair-json`\n7. Capture screenshot if needed.\n8. Stop both local servers with `Ctrl+C`.\n\n## Troubleshooting\n\n- If `uv run` fails with cache permission errors, rerun with `UV_CACHE_DIR=/tmp/uv-cache`.\n- If Flask modules are missing, keep using `uv run --with flask --with flask-cors ...`.\n- If output still matches production behavior, the fetch patch did not apply; reload and patch again before typing input.\n</yakaai_skills>"}