From 551b58d00421d84448a2f51d0e4d4fae9a5b0d47 Mon Sep 17 00:00:00 2001 From: Kevin Cusnir Date: Mon, 14 Sep 2026 10:11:16 +0300 Subject: [PATCH] =?UTF-8?q?ci:=20automatizar=20Dependabot=20y=20exigir=20l?= =?UTF-8?q?os=20catalogos=20al=20publicar=20=F0=9F=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What changed - .github/workflows/dependabot-auto-merge.yml: arma el auto-merge de parches y menores de Dependabot. Mayores y cambios de mantenedor esperan a Kevin. - .github/dependabot.yml: sigue mensual; anade hora, zona Asia/Jerusalem y cooldown (3 dias parche, 7 menor, 30 mayor; 7 las acciones). - quality.yml, via tools/nova_ultimate.py: el paso de catalogos es aviso en PR y en push a main, y fallo en una etiqueta v* o en workflow_dispatch. El CI se dispara tambien con las etiquetas v*. - tools/nova_ultimate.py escribia un dependabot.yml sin grupos: volver a ejecutarlo habria borrado la agrupacion en silencio. Ahora escribe el mismo contenido que el repo. - reports/nova regenerados con git add antes de generar. Why Cada fusion de Dependabot dejaba los catalogos viejos y ponia main en rojo sin nada roto, con su aviso de "workflow run failed". Lo que se publica en este repo son las etiquetas (v1.1.0, v1.1.1, v1.2.0), asi que los catalogos se exigen ahi. Es el mismo cambio que IvritSheli hace con su manifiesto en el mismo dia. Verification - python -m unittest discover -s tests/python -> 65 OK, incluido test_nova_generator: generador y quality.yml coinciden byte a byte - refresh_structure_catalogs --check, validate_repository_structure, validate_readme_visuals, validate_display_titles -> PASS Creative-Signature: Lirioth Teltanion Co-Authored-By: Claude Opus 5 --- .github/dependabot.yml | 15 ++++++ .github/workflows/dependabot-auto-merge.yml | 58 +++++++++++++++++++++ .github/workflows/quality.yml | 3 +- reports/nova/README.md | 6 +-- reports/nova/catalog_manifest.json | 8 +-- reports/nova/exercise_catalog.md | 6 +-- reports/nova/file_inventory.csv | 15 +++--- reports/nova/tree.txt | 9 ++-- tools/nova_ultimate.py | 13 +++-- 9 files changed, 106 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/dependabot-auto-merge.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6df141d..f90604b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,12 +3,23 @@ version: 2 # Misma filosofia que NovaMusicLab y IvritSheli: las subidas menores y de # parche llegan agrupadas en un solo PR, y las de version mayor sueltas, # porque son las unicas que pueden romper el build. +# +# cooldown desde el 14 sep 2026: una version recien publicada espera antes de +# proponerse, y una mayor espera un mes. Las alertas de seguridad no siguen este +# calendario. Menores y parches se fusionan solos al pasar las comprobaciones +# (.github/workflows/dependabot-auto-merge.yml); las mayores esperan a Kevin. updates: - package-ecosystem: npm directory: / schedule: interval: monthly + time: "06:40" + timezone: Asia/Jerusalem + cooldown: + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 open-pull-requests-limit: 5 groups: npm-minor-patch: @@ -19,6 +30,10 @@ updates: directory: / schedule: interval: monthly + time: "06:50" + timezone: Asia/Jerusalem + cooldown: + default-days: 7 open-pull-requests-limit: 5 groups: actions-all: diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 0000000..9148630 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,58 @@ +name: Dependabot auto-merge + +# Las actualizaciones de parche y menores se fusionan solas en cuanto pasan las +# comprobaciones obligatorias de la rama: esas comprobaciones son el revisor. +# +# Se quedan esperando a Kevin, sin excepcion: +# - las de version mayor, porque pueden romper sin que las pruebas lo vean +# (Tailwind 4 compilaba y pasaba las pruebas, pero perdia los colores propios); +# - cualquier actualizacion en la que haya cambiado el mantenedor del paquete, +# que es el patron tipico de un ataque a la cadena de suministro. +# +# Este workflow solo ARMA el auto-merge. Si una comprobacion falla, GitHub no +# fusiona nada: no hay forma de que este fichero salte una puerta de calidad. + +on: + pull_request: + types: [opened, reopened, synchronize] + +permissions: + contents: write + pull-requests: write + +jobs: + arm-auto-merge: + name: Arm auto-merge for safe Dependabot updates + if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository_owner == 'LiriothTeltanion' + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Read Dependabot metadata + id: meta + uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 + + - name: Arm auto-merge for patch, minor and digest updates + if: >- + steps.meta.outputs.update-type != 'version-update:semver-major' + && steps.meta.outputs.maintainer-changes != 'true' + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Leave major updates and maintainer changes for Kevin + if: >- + steps.meta.outputs.update-type == 'version-update:semver-major' + || steps.meta.outputs.maintainer-changes == 'true' + # Los valores entran por variables de entorno y no interpolados en el + # script: un nombre de paquete no debe poder ejecutarse como shell. + run: >- + echo "::notice title=Waiting for Kevin::$NAMES $FROM -> $TO + ($KIND, maintainer changed: $MAINTAINER)" + env: + NAMES: ${{ steps.meta.outputs.dependency-names }} + FROM: ${{ steps.meta.outputs.previous-version }} + TO: ${{ steps.meta.outputs.new-version }} + KIND: ${{ steps.meta.outputs.update-type }} + MAINTAINER: ${{ steps.meta.outputs.maintainer-changes }} diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 2bdbc6c..e294570 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -3,6 +3,7 @@ name: NOVA Quality Gate on: push: branches: [main] + tags: ['v*'] pull_request: workflow_dispatch: @@ -55,7 +56,7 @@ jobs: run: npm run verify:structure:core - name: Generated catalogs are current - continue-on-error: ${{ github.event_name == 'pull_request' }} + continue-on-error: ${{ github.ref_type != 'tag' && github.event_name != 'workflow_dispatch' }} run: npm run catalogs:check - name: Python anchor tests diff --git a/reports/nova/README.md b/reports/nova/README.md index 0cf1605..c79c6f6 100644 --- a/reports/nova/README.md +++ b/reports/nova/README.md @@ -1,17 +1,17 @@ # NOVA Reports — Status and Lineage -## Current structural evidence (2026-09-13) +## Current structural evidence (2026-09-14) - [Canonical exercise catalog](exercise_catalog.md) — 124 indexed exercise families; runtime and mastery remain unverified. - `exercise_catalog_metadata.csv` — versioned structural labels and review-entry hints; semantic titles/goals/technologies are derived conservatively and do not prove runtime or assignment correctness. - `exercise_catalog.csv` — machine-readable canonical path catalog. - `file_inventory.csv` — indexed-blob inventory (self-entry intentionally excluded to avoid a recursive hash). -- `tree.txt` — exact-case tree for 891 Git-indexed files. +- `tree.txt` — exact-case tree for 892 Git-indexed files. - `rename_plan.csv` — unapproved later-wave proposals only. - `catalog_manifest.json` — generation date, base HEAD, and stable source-index fingerprint. - [`../resume/`](../resume/) — Wave 0 baseline, duplicate accounting, decisions, test map, and open-work triage. -Generation basis: HEAD `ee665a4047b5c38d54cc1507e0fd91827141f49c` plus the staged source index fingerprint `sha256:990f56cd7164669bca14b3783f5c430b8418318f2096407de70dec185ed1ebe4`. The versioned metadata source is included; generated catalog outputs are excluded to avoid self-reference. +Generation basis: HEAD `727cf0b5efa64c41bcb3ffb07b30a8a71103af83` plus the staged source index fingerprint `sha256:1340dbc4b2a8ea55e5b3c692306c400ee05c20db115d51841d662c373f91f8b0`. The versioned metadata source is included; generated catalog outputs are excluded to avoid self-reference. Regenerate with `python tools/refresh_structure_catalogs.py --repo . --write`; verify drift with `python tools/refresh_structure_catalogs.py --repo . --check`. diff --git a/reports/nova/catalog_manifest.json b/reports/nova/catalog_manifest.json index 88da0ee..cab28a8 100644 --- a/reports/nova/catalog_manifest.json +++ b/reports/nova/catalog_manifest.json @@ -1,10 +1,10 @@ { "schema_version": 2, - "generated_on": "2026-09-13", + "generated_on": "2026-09-14", "generator": "tools/refresh_structure_catalogs.py", - "base_head": "ee665a4047b5c38d54cc1507e0fd91827141f49c", - "source_index_sha256": "990f56cd7164669bca14b3783f5c430b8418318f2096407de70dec185ed1ebe4", - "source_index_file_count": 884, + "base_head": "727cf0b5efa64c41bcb3ffb07b30a8a71103af83", + "source_index_sha256": "1340dbc4b2a8ea55e5b3c692306c400ee05c20db115d51841d662c373f91f8b0", + "source_index_file_count": 885, "fingerprint_excludes": [ "reports/nova/catalog_manifest.json", "reports/nova/exercise_catalog.csv", diff --git a/reports/nova/exercise_catalog.md b/reports/nova/exercise_catalog.md index 1a6837e..fdd80ba 100644 --- a/reports/nova/exercise_catalog.md +++ b/reports/nova/exercise_catalog.md @@ -1,9 +1,9 @@ # Canonical Exercise Catalog -> Regenerated from the exact Git index on `2026-09-13` by `tools/refresh_structure_catalogs.py`. +> Regenerated from the exact Git index on `2026-09-14` by `tools/refresh_structure_catalogs.py`. -- Base HEAD: `ee665a4047b5c38d54cc1507e0fd91827141f49c` -- Source-index fingerprint: `sha256:990f56cd7164669bca14b3783f5c430b8418318f2096407de70dec185ed1ebe4` (generated outputs excluded) +- Base HEAD: `727cf0b5efa64c41bcb3ffb07b30a8a71103af83` +- Source-index fingerprint: `sha256:1340dbc4b2a8ea55e5b3c692306c400ee05c20db115d51841d662c373f91f8b0` (generated outputs excluded) This catalog proves repository presence and path integrity only. It does not prove that an exercise runs, that Kevin can explain it, or that it is mastered or portfolio-ready. diff --git a/reports/nova/file_inventory.csv b/reports/nova/file_inventory.csv index 3c73a79..d68a74f 100644 --- a/reports/nova/file_inventory.csv +++ b/reports/nova/file_inventory.csv @@ -9,10 +9,11 @@ path,size_bytes,lines,extension,language,category,binary,sha256,encoding,tracked .gitattributes,657,46,[no extension],Other,configuration,False,b4f8d1af2ab405eb246f97f7e8bbdf8795e665cd6901a6534585de33fb379253,utf-8,True,,,,,,False,False,0,0,False,, .github/INTERNAL_GUIDE.md,4815,87,.md,Markdown,documentation,False,a331cf469dda4f9d613713bb393d6e6c923eccbce3ca05aed81848493d537401,utf-8,True,,,,,,False,False,0,0,False,, .github/copilot-instructions.md,3030,79,.md,Markdown,documentation,False,eae3180385eeddfbf4944c9a6328efa094110918f03bdf68b31b800d574dd811,utf-8,True,,,,,,False,False,0,0,False,, -.github/dependabot.yml,612,25,.yml,YAML,configuration,False,f01a06a75247097f0b9ad45d7ec9a60b1a8a5b6eb0fdbf569061bf73df700080,utf-8,True,,,,,,False,False,0,0,False,, +.github/dependabot.yml,1163,40,.yml,YAML,configuration,False,00730bba5bdb9e9af3bcf57d542ed662e90c6bcc367079f793bd394415ac4895,utf-8,True,,,,,,False,False,0,0,False,, .github/pull_request_template.md,1631,58,.md,Markdown,documentation,False,758e587b003b26a60248310d4d9f74bc580f5ce34d216f0a58f6edd061ae1418,utf-8,True,,,,,,False,False,0,0,False,, .github/workflows/README.md,1529,57,.md,Markdown,documentation,False,6cfde94b6754fb79c70250e9bd0916d3c7518dac4322210cf4ad6a6721046b18,utf-8,True,,,,,,False,True,0,0,False,, -.github/workflows/quality.yml,1629,65,.yml,YAML,configuration,False,179c039d6d7970a42464c28966db7af26b4e7942624ca2da379790b087abf319,utf-8,True,,,,,,False,False,0,0,False,, +.github/workflows/dependabot-auto-merge.yml,2420,58,.yml,YAML,configuration,False,93199674a4b0d4a249ead6424eaa1446873886e8ee30faf567c0e40f97bd75b0,utf-8,True,,,,,,False,False,0,0,False,, +.github/workflows/quality.yml,1679,66,.yml,YAML,configuration,False,92b316a4189bdf61e49bf08b972a5a7ad0dd1e0ac0c6ecc24b01e8cb8a09e5aa,utf-8,True,,,,,,False,False,0,0,False,, .gitignore,1149,84,[no extension],Other,configuration,False,2bdb8d03e1e79777456585cf4161bd7b94fb87b4461e0d9cab86d54fdea74024,utf-8,True,,,,,,False,False,0,0,False,, .learning/OCTOPUS_INTAKE.md,9466,232,.md,Markdown,documentation,False,994644a4ea7f9d25982f741d8035508669fa83ccb14d93b4c5198089c61953b7,utf-8,True,,,,,,False,False,0,0,False,, .learning/PROGRESS.md,6120,57,.md,Markdown,documentation,False,d0588ccdbf474b5ae0aead4365c706339aa6c7b62fc89aeb9b061958f38ce572,utf-8,True,,,,,,False,False,0,0,False,, @@ -832,12 +833,12 @@ package.json,2385,48,.json,JSON,configuration,False,333c4be6c77d41b670eda1740590 pyproject.nova.suggested.toml,322,13,.toml,TOML,configuration,False,9263ac0848aae33c2457615c43d74743b147ba0667a221ee13e1917a9ff29588,utf-8,True,,,,,,False,False,0,0,False,, pyproject.toml,266,12,.toml,TOML,configuration,False,360334d4408c8b554e53902b326e1590c7698f9324401c1a3860cafe4b3d56fb,utf-8,True,,,,,,False,False,0,0,False,, reports/nova/NOVA_UPDATE_REPORT.md,127431,599,.md,Markdown,report,False,c27fb330404d829c6b497fe4f2e69f354d8b8a5f67c5316e0ca58730d43234ed,utf-8,True,,,,,,False,False,6,0,False,, -reports/nova/README.md,2186,29,.md,Markdown,report,False,3ff684e2f356c35e4dbe1edce95c4d0d1a9895a71363cd4a1c2d1b74dc724ab3,utf-8,True,,,,,,False,True,0,0,False,, +reports/nova/README.md,2186,29,.md,Markdown,report,False,c48f97ca46e025cc5086a266adedb2f5a8ed4adac9476ffcecd0fc3b14ad9f6e,utf-8,True,,,,,,False,True,0,0,False,, reports/nova/README.nova.generated.md,1718,48,.md,Markdown,report,False,94dee5fa611da50821672f4470cabf53997810f684b30eb5e905c0bba3fae9c1,utf-8,True,,,,,,False,False,0,0,False,, reports/nova/SUMMARY.txt,396,20,.txt,Text,report,False,fcbc7c88da5327c6230cb8402cbd71b689c8a18aba7ffd260079da58d135e256,utf-8,True,,,,,,False,False,0,0,False,, -reports/nova/catalog_manifest.json,777,19,.json,JSON,report,False,85128e1652804927b056b5e92e37dd81ce547ab71b45c9b353c2672286e27628,utf-8,True,,,,,,False,False,0,0,False,, +reports/nova/catalog_manifest.json,777,19,.json,JSON,report,False,e720bbde71f591743f77a955a1ca11bcb12c041d433aeb1ebdca45f544e7bb3d,utf-8,True,,,,,,False,False,0,0,False,, reports/nova/exercise_catalog.csv,92050,125,.csv,Other,report,False,6e5d30135cf3130a284410e6c7edcb835df81acfef0d09d42ef264692bb3897b,utf-8,True,,,,,,False,False,9,0,False,, -reports/nova/exercise_catalog.md,31658,140,.md,Markdown,report,False,1c80124c2f68beeeecf52837c5f792ff2f63d44428fb2a91297164c0fc9a693a,utf-8,True,,,,,,False,False,2,0,False,, +reports/nova/exercise_catalog.md,31658,140,.md,Markdown,report,False,6b51d6f4f6f6e76de6e1a2ca6294cb0f79c5b0024fb57b3c33160e4bc5edb55c,utf-8,True,,,,,,False,False,2,0,False,, reports/nova/exercise_catalog_metadata.csv,25780,125,.csv,Other,report,False,c4706fa1ee009eb78e2b2988af9889afd2ab6de463b43b70bd6a0540373c10d2,utf-8,True,,,,,,False,False,2,0,False,, reports/nova/next_actions.md,4317,139,.md,Markdown,report,False,49ebbf20f3c5bf7670cfa9b4add9af85332db1120c39936b4ccec270c4cb1339,utf-8,True,,,,,,False,False,0,24,False,, reports/nova/nova_repo_audit.json,23406,700,.json,JSON,report,False,e674e1fbad6c420528fb04e1a9280fd4c62ea7af95f391b20f20b84a1e449248,utf-8,True,,,,,,False,False,0,0,False,, @@ -846,7 +847,7 @@ reports/nova/nova_repo_dashboard.html,26307,12,.html,HTML,report,False,9f5a2e1cd reports/nova/quality_report.json,441,18,.json,JSON,report,False,b8922e175b9d956ecd0060eb981504a9ee1004499447b0e40d68097a4c7830b6,utf-8,True,,,,,,False,False,0,0,False,, reports/nova/quality_report.md,195,10,.md,Markdown,report,False,031b2259d428fb7a5d266a8423cf620ecf4b6c6632781329cd8a8e6878e45dc2,utf-8,True,,,,,,False,False,0,0,False,, reports/nova/rename_plan.csv,567,3,.csv,Other,report,False,b7a9dcd3b3748a421cf8aeebed8586edaec4cde60a8ad199b08ec6d4a5143e3b,utf-8,True,,,,,,False,False,0,0,False,, -reports/nova/tree.txt,54478,1173,.txt,Text,report,False,5ca1fc58e54dea9f57a3c63d3ed8cf54a732b86c74e0607c649e035cf268817a,utf-8,True,,,,,,False,False,6,0,False,, +reports/nova/tree.txt,54526,1174,.txt,Text,report,False,a24826afaf65abc5e84c1b4a7d41cfeb24cb191347a35f735fdb3df9e7bce2e9,utf-8,True,,,,,,False,False,6,0,False,, reports/resume/ACADEMY_ALIGNMENT_2026-08-24.md,7808,94,.md,Markdown,report,False,39e25aeb1afee64263c7495de7964d0d948acc033c751490dd96a758b7c290d8,utf-8,True,,,,,,False,False,0,0,False,, reports/resume/BASELINE_2026-08-23.md,6749,104,.md,Markdown,report,False,6e14d59d7cdf28289052d1ab2a94a1f42f150ecd29346c6a4213789f05966f1a,utf-8,True,,,,,,False,False,0,0,False,, reports/resume/CONSOLIDATION_RESULT.md,3175,47,.md,Markdown,report,False,9a6554749af2df88f472af280356bc9bea0b62c16a0afce27aeed7cbf33f9e8f,utf-8,True,,,,,,False,False,0,0,False,, @@ -882,7 +883,7 @@ tools/README.md,1582,60,.md,Markdown,documentation,False,2ba5c544da8e2b3ad455c24 tools/check_typescript_syntax.mjs,2140,64,.mjs,JavaScript,source,False,69e49d42e6dbe5100c08b2ca057357b828582f3b33eb0439da348aa61d5b39fd,utf-8,True,,,,,,False,False,0,0,False,, tools/learning_intake.py,21220,550,.py,Python,source,False,6b0784d6312f5fcf675f1c0986fcab088eb50badbe84a92d99527e8bcff5fa8e,utf-8,True,,,,,,False,False,0,0,False,, tools/nova_quality_gate.py,15551,362,.py,Python,source,False,719964bfc16055bceae7491a0dea87199a8bf8c3379ff4eada71483b338263a3,utf-8,True,,,,,,False,False,0,0,False,, -tools/nova_ultimate.py,103213,1952,.py,Python,source,False,22f77c453f206d4b2214aa640f6d8423ec182f9972b70711e524e5f30093319d,utf-8,True,,,,,,False,False,1,0,False,, +tools/nova_ultimate.py,104420,1955,.py,Python,source,False,090711d6372b294979f3b59f800157020762e51e47c00abfa72e0ce6ff902558,utf-8,True,,,,,,False,False,1,0,False,, tools/refresh_structure_catalogs.py,27389,678,.py,Python,source,False,7564e71752df3f7501b70c0c7a006aadbe762d7094adb7346ce8f5386712bfae,utf-8,True,,,,,,False,False,2,0,False,, tools/run_node_tests.mjs,918,29,.mjs,JavaScript,source,False,93c83a13cc3a13d41d84b189ffc739e96756f9d120978663ff7beeca0cdf5455,utf-8,True,,,,,,False,False,0,0,False,, tools/validate_display_titles.py,9408,258,.py,Python,source,False,118f2367f90ee76b326019c665ee0e1c2a436bec46346e26dfe23a33e64ce355,utf-8,True,,,,,,False,False,0,0,False,, diff --git a/reports/nova/tree.txt b/reports/nova/tree.txt index 2f2219f..96976c1 100644 --- a/reports/nova/tree.txt +++ b/reports/nova/tree.txt @@ -1,8 +1,8 @@ Fullstack2026 canonical Git-index tree -Regenerated: 2026-09-13 -Base HEAD: ee665a4047b5c38d54cc1507e0fd91827141f49c -Source-index SHA-256 (generated outputs excluded): 990f56cd7164669bca14b3783f5c430b8418318f2096407de70dec185ed1ebe4 -Indexed files: 891 +Regenerated: 2026-09-14 +Base HEAD: 727cf0b5efa64c41bcb3ffb07b30a8a71103af83 +Source-index SHA-256 (generated outputs excluded): 1340dbc4b2a8ea55e5b3c692306c400ee05c20db115d51841d662c373f91f8b0 +Indexed files: 892 . ├── .ai @@ -13,6 +13,7 @@ Indexed files: 891 │ └── VISUAL_SYSTEM.md ├── .github │ ├── workflows +│ │ ├── dependabot-auto-merge.yml │ │ ├── quality.yml │ │ └── README.md │ ├── copilot-instructions.md diff --git a/tools/nova_ultimate.py b/tools/nova_ultimate.py index 23d8b89..5845988 100644 --- a/tools/nova_ultimate.py +++ b/tools/nova_ultimate.py @@ -688,7 +688,7 @@ def update_package_json(root: Path, changes: list[Change]) -> None: def write_ci(root: Path, changes: list[Change]) -> None: - workflow = """name: NOVA Quality Gate\n\non:\n push:\n branches: [main]\n pull_request:\n workflow_dispatch:\n\npermissions:\n contents: read\n\nconcurrency:\n group: nova-quality-${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n validate:\n name: Syntax, security, docs and tests\n runs-on: ubuntu-latest\n timeout-minutes: 20\n steps:\n - name: Checkout repository\n uses: actions/checkout@v7\n\n - name: Set up Python\n uses: actions/setup-python@v7\n with:\n python-version: \"3.13\"\n\n - name: Set up Node.js\n uses: actions/setup-node@v7\n with:\n node-version: \"24\"\n cache: npm\n\n - name: Install JavaScript tooling\n run: npm ci\n\n - name: Whole-repository quality gate\n run: python tools/nova_quality_gate.py --repo . --strict\n\n - name: Python anchor tests\n run: python -m unittest discover -s tests/python -p \"test_*.py\" -v\n\n - name: JavaScript and TypeScript anchor tests\n run: npm run test:js\n""" + workflow = """name: NOVA Quality Gate\n\non:\n push:\n branches: [main]\n tags: ['v*']\n pull_request:\n workflow_dispatch:\n\npermissions:\n contents: read\n\nconcurrency:\n group: nova-quality-${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n validate:\n name: Syntax, security, docs and tests\n runs-on: ubuntu-latest\n timeout-minutes: 20\n steps:\n - name: Checkout repository\n uses: actions/checkout@v7\n\n - name: Set up Python\n uses: actions/setup-python@v7\n with:\n python-version: \"3.13\"\n\n - name: Set up Node.js\n uses: actions/setup-node@v7\n with:\n node-version: \"24\"\n cache: npm\n\n - name: Install JavaScript tooling\n run: npm ci\n\n - name: Whole-repository quality gate\n run: python tools/nova_quality_gate.py --repo . --strict\n\n - name: Python anchor tests\n run: python -m unittest discover -s tests/python -p \"test_*.py\" -v\n\n - name: JavaScript and TypeScript anchor tests\n run: npm run test:js\n""" install_steps = ( " - name: Install JavaScript tooling\n" " run: npm ci --ignore-scripts\n\n" @@ -720,19 +720,22 @@ def write_ci(root: Path, changes: list[Change]) -> None: ) # Los catalogos de reports/nova indexan el arbol entero, asi que cualquier # fichero que cambie los deja obsoletos y todo PR nacia fallando, Dependabot - # incluido. Van en su propio paso: aviso en una rama, fallo en push a main, - # que es lo que se publica. El resto de la estructura no se ablanda. + # incluido. Van en su propio paso. Desde el 14 sep 2026 son aviso en una rama + # y en push a main, y fallo en una etiqueta v* o en una ejecucion manual: cada + # fusion de Dependabot ponia main en rojo sin nada roto, y lo que se publica es + # la etiqueta. Antes de etiquetar: git add, npm run catalogs:refresh y fusionar. + # El resto de la estructura no se ablanda. workflow = workflow.replace( "\n - name: Python anchor tests", "\n - name: Canonical repository structure\n" " run: npm run verify:structure:core\n\n" " - name: Generated catalogs are current\n" - " continue-on-error: ${{ github.event_name == 'pull_request' }}\n" + " continue-on-error: ${{ github.ref_type != 'tag' && github.event_name != 'workflow_dispatch' }}\n" " run: npm run catalogs:check\n\n" " - name: Python anchor tests", ) write_text(root / ".github/workflows/quality.yml", workflow, changes, "added read-only CI quality gate") - dependabot = """version: 2\nupdates:\n - package-ecosystem: npm\n directory: /\n schedule:\n interval: monthly\n open-pull-requests-limit: 5\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: monthly\n open-pull-requests-limit: 5\n""" + dependabot = 'version: 2\n\n# Misma filosofia que NovaMusicLab y IvritSheli: las subidas menores y de\n# parche llegan agrupadas en un solo PR, y las de version mayor sueltas,\n# porque son las unicas que pueden romper el build.\n#\n# cooldown desde el 14 sep 2026: una version recien publicada espera antes de\n# proponerse, y una mayor espera un mes. Las alertas de seguridad no siguen este\n# calendario. Menores y parches se fusionan solos al pasar las comprobaciones\n# (.github/workflows/dependabot-auto-merge.yml); las mayores esperan a Kevin.\n\nupdates:\n - package-ecosystem: npm\n directory: /\n schedule:\n interval: monthly\n time: "06:40"\n timezone: Asia/Jerusalem\n cooldown:\n semver-major-days: 30\n semver-minor-days: 7\n semver-patch-days: 3\n open-pull-requests-limit: 5\n groups:\n npm-minor-patch:\n patterns: ["*"]\n update-types: [minor, patch]\n\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: monthly\n time: "06:50"\n timezone: Asia/Jerusalem\n cooldown:\n default-days: 7\n open-pull-requests-limit: 5\n groups:\n actions-all:\n patterns: ["*"]\n' write_text(root / ".github/dependabot.yml", dependabot, changes, "added monthly dependency updates")