diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd10bc1..fd8420c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,10 +41,11 @@ jobs: print(f'argus {argus.__version__} — config OK, {len(cfg[\"tags\"])} workstreams') " # Proves the "works with no API key" promise, writing outside the repo so - # the committed dashboard is never touched by a test run. + # the committed dashboard is never touched by a test run. --force because + # the template ships with the sweep switched off; CI must still exercise it. - name: Pipeline runs end-to-end with no secrets at all run: | - python -m argus.run --stage score --db "$RUNNER_TEMP/ci.db" - python -m argus.run --stage render --db "$RUNNER_TEMP/ci.db" --out "$RUNNER_TEMP/index.html" + python -m argus.run --stage score --db "$RUNNER_TEMP/ci.db" --force + python -m argus.run --stage render --db "$RUNNER_TEMP/ci.db" --out "$RUNNER_TEMP/index.html" --force grep -q "" "$RUNNER_TEMP/index.html" git diff --exit-code # a test run must leave the tree clean diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index c935466..750141f 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -14,7 +14,32 @@ permissions: id-token: write # required by actions/deploy-pages issues: write # open a failure alert jobs: + # The master switch, read before anything expensive happens. A disabled repo + # spends a few seconds here and nothing else — no dependency install, no + # collection, no Pages deploy. A manual dispatch runs regardless, so you can + # always try a sweep without editing config. + gate: + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + enabled: ${{ steps.check.outputs.enabled }} + steps: + - uses: actions/checkout@v4 + - id: check + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "enabled=true" >> "$GITHUB_OUTPUT" + echo "manual dispatch — running regardless of the config switch" + elif grep -qiE '^enabled:[[:space:]]*(false|no|off)([[:space:]]*#.*)?$' config.yaml; then + echo "enabled=false" >> "$GITHUB_OUTPUT" + echo "::notice::Scheduled sweep is switched off. Set 'enabled: true' in config.yaml once your sources are configured. Run this workflow manually to try a one-off sweep." + else + echo "enabled=true" >> "$GITHUB_OUTPUT" + fi + run: + needs: gate + if: needs.gate.outputs.enabled == 'true' runs-on: ubuntu-latest timeout-minutes: 20 # a wedged collector should fail the run, not hang for 6h steps: @@ -81,10 +106,12 @@ jobs: uses: ./.github/workflows/pages.yml permissions: {contents: read, pages: write, id-token: write} - # `always()` so a failed sweep still alerts — that is the entire point. + # `always()` so a failed sweep still alerts — that is the entire point. Gated + # on the switch too, so a deliberately-off repo doesn't spin a runner to + # report that nothing happened. alert: - needs: run - if: always() + needs: [gate, run] + if: always() && needs.gate.outputs.enabled == 'true' uses: ./.github/workflows/alert.yml with: {conclusion: "${{ needs.run.result }}"} permissions: {contents: read, issues: write} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2387856..79ee73e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,18 @@ publish a tag that disagrees with it. ## [Unreleased] +### Added + +- **A master switch: `enabled` in `config.yaml`.** `false` means scheduled + sweeps do nothing — no collection, no scoring, no commit — while a manual run + of the pipeline workflow still works. Checked in a cheap `gate` job before any + dependency install, so a switched-off repository costs seconds rather than a + full sweep. `--force` overrides it locally. +- The template now ships with `enabled: false`. It was sweeping every 8 hours + for the example field, and — worse — whatever it collected became the starting + data of every repository created from it. The committed database and dashboard + are reset to empty for the same reason. + ## [1.3.0] — 2026-08-09 ### Added diff --git a/Makefile b/Makefile index e9cbdbf..a4291e6 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,9 @@ install: dry-run: ## collect + per-source counts, no writes python -m argus.run --dry-run +# ARGS passes flags through, e.g. make run ARGS=--force while `enabled: false` run: ## full pipeline (keyword mode unless a provider key is set) - python -m argus.run + python -m argus.run $(ARGS) collect: python -m argus.run --stage collect diff --git a/README.md b/README.md index 2b0d942..51a79b3 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ file. Works with **no API key** (keyword scoring) and **no email** (dashboard only) — every capability degrades cleanly when its secret is absent, and a run prints which scorer it actually used. +> **A fresh copy starts switched off.** `config.yaml` ships with +> `enabled: false` so it doesn't sweep for the example field before it's yours. +> Set `enabled: true` once your sources are configured — step 5 below. + > This is a **fork-per-person template**. Each researcher runs their own copy, > pointed at their own topics. It ships configured for one example field > (Southeast-Asia power systems) so it runs out of the box — replace that config @@ -36,7 +40,11 @@ prints which scorer it actually used. few-shot examples for your work. This is the system prompt used for LLM scoring. 4. **Pick a scorer** — see the table below. The free keyword scorer needs nothing; an LLM scorer needs one API key, and several are free. -5. **Turn on Actions and Pages.** Two one-time switches in your fork: +5. **Switch it on.** `config.yaml` ships with `enabled: false`, so a fresh + copy doesn't sweep for the example field before it's yours. Set + `enabled: true` when steps 1-3 are done. (A manual run of the pipeline + workflow always works, switch or no switch, if you want to try one first.) +6. **Turn on Actions and Pages.** Two one-time switches in your fork: - **Actions** tab → enable workflows (forks start with them disabled). - **Settings → Pages → Source: GitHub Actions** — needed once before the dashboard can publish. Skip it and everything still works; the sweep just @@ -193,13 +201,27 @@ your scoring provider unless `digest.synthesis_provider` says otherwise. ```bash make install # pip install -r requirements.txt make dry-run # collect + per-source counts, no writes -make run # full pipeline +make run # full pipeline (ARGS=--force while `enabled: false`) make test # offline unit tests — no network, no keys make journals # find a journal's ISSN by name, or audit your watchlist make vacuum # reclaim DB space after pruning (occasional; see below) open docs/index.html ``` +### Pausing it + +`enabled: false` in `config.yaml` stops scheduled sweeps entirely — no +collection, no scoring, no commits. Useful for a template, and equally for going +on leave or quieting a radar you're mid-way through retuning. + +It's checked before anything expensive happens, so a paused repo costs a few +seconds per schedule rather than a full sweep. Running the pipeline workflow +**manually still works** either way, and locally you can force one: + +```bash +make run ARGS=--force +``` + ### Sweep cadence and the commit log Each sweep appends to a per-source run log, so the SQLite file changes every diff --git a/argus/run.py b/argus/run.py index a1246ce..2a69114 100644 --- a/argus/run.py +++ b/argus/run.py @@ -34,6 +34,21 @@ def _read(path: str) -> str: return f.read() +def enabled(cfg: dict) -> bool: + """Is the sweep switched on? Defaults to True, so an existing config that + predates this switch keeps running. + + The template ships with it off. Two reasons: a template shouldn't burn + Actions minutes collecting for an example field nobody is reading, and + whatever it collected would otherwise become the starting data of every + repository created from it. + """ + value = cfg.get("enabled", True) + if isinstance(value, str): + return value.strip().lower() not in ("false", "no", "off", "0", "") + return bool(value) + + def _library_due(conn, lib_cfg: dict) -> bool: """Library discovery runs at most every `every_days` (default 7) — it's a weekly shortlist, not something to rebuild every 4h. dry-run (conn=None) always runs.""" @@ -136,6 +151,16 @@ def score(conn, cfg: dict, kw: dict, mode: str, spec: dict) -> dict: def run_pipeline(args) -> int: cfg = _load_yaml(args.config) + + # The master switch. Off means a scheduled sweep does nothing at all: no + # collection, no scoring, no commit. `--force` overrides it so you can still + # try a run by hand without editing config. + if not enabled(cfg) and not args.force: + print("sweep disabled — config.yaml has `enabled: false`. " + "Set it to true once your sources are configured, " + "or run with --force for a one-off.") + return 0 + sources = _load_yaml(os.path.join(ROOT, "registry", "sources.yaml")) kw = sources.get("keywords", {}) window_days = cfg.get("window_days", 7) @@ -195,6 +220,8 @@ def main(argv=None) -> int: p.add_argument("--db", default=None) p.add_argument("--out", default=None, help="dashboard path (default docs/index.html)") p.add_argument("--dry-run", action="store_true") + p.add_argument("--force", action="store_true", + help="run even when config.yaml has `enabled: false`") p.add_argument("--vacuum", action="store_true", help="reclaim space after pruning (rewrites the whole file — occasional, not scheduled)") p.add_argument("--force-digest", action="store_true") diff --git a/config.yaml b/config.yaml index 6c9f7a6..a56accb 100644 --- a/config.yaml +++ b/config.yaml @@ -3,6 +3,16 @@ # * edit registry/sources.yaml (your queries, journals, feeds, keywords) # * edit `tags` (your workstreams) and prompts/research.md (your profile+rubric) # * pick a scoring provider below (several are free) +# MASTER SWITCH. `false` means scheduled sweeps do nothing at all — no +# collection, no scoring, no commit. A manual run of the pipeline workflow still +# works, so you can try one without editing this. +# +# It ships OFF in the template on purpose: an unconfigured copy would otherwise +# collect for the example field below, burn Actions minutes, and hand whatever +# it gathered to the next person who uses the template as their starting data. +# Turn it on once steps 1-3 of the README are done and your sources are yours. +enabled: false + title: "ARGUS" window_days: 7 # collectors ignore items older than this diff --git a/data/argus.db b/data/argus.db index 2bc28ae..d2f7d8e 100644 Binary files a/data/argus.db and b/data/argus.db differ diff --git a/docs/index.html b/docs/index.html index c643bca..1144370 100644 --- a/docs/index.html +++ b/docs/index.html @@ -95,7 +95,7 @@ <div class="wrap"> <header> <div class="brand"><h1>ARGUS</h1></div> - <div class="stamp"><span class="dot"></span>updated 2026-08-09 02:30 UTC</div> + <div class="stamp"><span class="dot"></span>updated 2026-08-09 03:49 UTC</div> </header> @@ -106,475 +106,13 @@ - <div class="sec"><h2>Recent</h2><span class="rule"></span><span class="count">29 items</span></div> + <div class="sec"><h2>Recent</h2><span class="rule"></span><span class="count">0 items</span></div> - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score hi">8</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.epsr.2026.113949">Economic optimization dispatch of microgrids based on finite-time dynamic event-triggered algorithms</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Electric Power Systems Research</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-07"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">7</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.epsr.2026.113876">Two-level stochastic programming for optimal operation of wind-thermal-hydropower systems in day-ahead and balancing markets</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Electric Power Systems Research</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-07"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">7</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.epsr.2026.113942">Research on Bi-level cooperative optimization algorithm of wind turbine layout and cable topology in floating offshore wind farm</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Electric Power Systems Research</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-07"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.epsr.2026.113946">Voltage sag support strategy based on cooperative optimization control of photovoltaic inverter currents</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Electric Power Systems Research</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-07"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.epsr.2026.113915">Location-aware reactive power control for V2G-enabled distribution networks: Optimization framework and real-time embedded validation</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Electric Power Systems Research</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-07"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score hi">8</span> - <div class="body"> - <a class="title" href="https://arxiv.org/abs/2608.05567v1">SDDmiP.jl: A Software Package with a Provably Convergent Benders Algorithm for Multi-Stage Stochastic Mixed-Integer Programming</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>arXiv</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-06"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score">7</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.enpol.2026.115518">Impact of renewable energy communities on the Italian day-ahead electricity market: A scenario analysis</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>Energy Policy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-06"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE7733"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://arxiv.org/abs/2608.05901v1">From Value Bounds to Policy-Distance and Active-Face Certificates: Same-Grid Duality for Constrained Dynamic Portfolios</a> - <div class="meta"> - <span class="chip">Stakeholder intel</span> - <span>arXiv</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-06"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score hi">10</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128552">Can Italy decarbonise without raising bills? A scenario-based assessment of renewable, flexibility and adequacy policies on power system costs through 2035</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score hi">9</span> - <div class="body"> - <a class="title" href="https://arxiv.org/abs/2608.05413v1">A Relaxation-Based Decomposition Approach for Solving a Supported-Evacuation Problem in Wildfires</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>arXiv</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score hi">8</span> - <div class="body"> - <a class="title" href="https://doi.org/10.22541/authorea.15007070/v1">Integrated Nuclear–Renewable Hybrid Energy Systems for Energy Security and Long-Term Decarbonization: A Sustainable Energy Approach for Sumba Island</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>openalex:Indonesia power system planning (preprint)</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">7</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.esd.2026.102095">Multi-objective neural networks-based aerodynamic shape optimization and performance analysis of vertical axis wind turbine blade profile</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy Sustainable Development/Energy for sustainable development</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.esd.2026.102097">Resource-driven regulatory indicators for sustainable energy: Modern renewables and efficiency challenges in achieving SDG 7 in Asia</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>Energy Sustainable Development/Energy for sustainable development</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://arxiv.org/abs/2608.05460v1">A proximal subgradient method for nonconvex stochastic optimization under the Kurdyka-Łojasiewicz condition</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>arXiv</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://news.google.com/rss/articles/CBMiYEFVX3lxTE9jY2FHT0ZCNnpzdkRfcWNxZDhjcVNkamI1dHNycWY4S0xJX2ZxSl80Y05XV1FzbUpNcU15cnlJcVlKTkxWTVI4V2VSdlFOTGhydEs3WGlpY3VVbXNMRmw3WQ?oc=5">BGRIM Aligns Renewable Targets With Vietnam’s PDP8, Eyes 2,000MW Capacity by 2030 - kaohoon international</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>gnews:Vietnam PDP8 electricity</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-05"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#CC3311"> - <div class="top"> - <span class="score hi">9</span> - <div class="body"> - <a class="title" href="https://news.google.com/rss/articles/CBMiiwFBVV95cUxOQUFnVHJFMUtOdlZVNEZpQjBRN1RyT0dHZ21oMmNtLU1kMTFDcHA5Z0g0Z2ZPdzFxWDBQakJzTGpSTTJ5U1VkVV9WeWVncGQ5R2lLbzNxcmRLbzlBTzV0eDJpOV9hUnJBdGVsWjdnbTFOdnp0SlZTeWdCUFpXSldwZGRJR2tiU0ZQcE80?oc=5">Indonesia’s captive coal: Under-the-radar expansion - dialogue.earth</a> - <div class="meta"> - <span class="chip">Industrial power</span> - <span>gnews:captive coal nickel Indonesia</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-04"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score hi">8</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128588">Joint optimization of electric bus operation and battery charging considering renewable microgrid interactions</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-04"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128561">Distributionally robust capacity optimization for hydrogen-based multi-energy systems: Integrating chain-wide energy conversion characteristics under variable operating conditions</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-04"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.141984">Multi-objective optimization of double-H finned tube heat exchangers via CFD-DEM: Entropy generation, fouling, and erosion analysis</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-04"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">7</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128540">A novel yawed wake model capturing full-wake heterogeneity with application to layout-yaw co-optimization in utility-scale wind farms</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#888888"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.54337/ijsepm.11598">Sustainable energy planning with district heating , PV solar and hybrid wind-solar systems</a> - <div class="meta"> - <span class="chip">none</span> - <span>International Journal of Sustainable Energy Planning and Management</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.enpol.2026.115516">Managing stranded assets in Germany's gas distribution grid: Regulatory challenges and a just-transition policy roadmap</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>Energy Policy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128533">Optimizing the configuration and capacity of flexibility retrofits in multiple power plants using a bi-level optimization approach</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.142137">Multifunctional triply periodic minimal surface-based metal hydride reactors: Topology optimization for enhanced thermal transport and hydrogen storage</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#CC3311"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.142089">Multi-timescale optimal scheduling of an electrolytic aluminum industrial park: coupling of heterogeneous production processes and transmission-distribution dual risk</a> - <div class="meta"> - <span class="chip">Industrial power</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.142149">Optimization and offshore performance tests of low-velocity current energy blades with integrated winglets</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-03"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#33BBEE"> - <div class="top"> - <span class="score hi">10</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.apenergy.2026.128567">Electricity market reform proposals through the lens of the energy trilemma: A state-of-the-art review</a> - <div class="meta"> - <span class="chip">Market reform</span> - <span>Applied Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-02"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.142106">Operational parameter analysis and optimization of CFPP -TES coupled system based on combined main and reheat steam extraction</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-02"></span> - </div> - - </div> - </div> - </div> - - <div class="row" style="--c:#EE3377"> - <div class="top"> - <span class="score">6</span> - <div class="body"> - <a class="title" href="https://doi.org/10.1016/j.energy.2026.142143">In-depth exploration of trade-offs in multi-objective optimization operation of reservoir group: the interactions among socio-economic water, ecological water, and hydropower generation in arid regions</a> - <div class="meta"> - <span class="chip">Methods & tools</span> - <span>Energy</span> - <span class="sep">·</span> - <span class="ago" data-date="2026-08-02"></span> - </div> - - </div> - </div> - </div> + <p class="empty">No research items above threshold yet.</p> <footer> - 29 items · scorer: <code>keyword</code> + 0 items · scorer: <code>keyword</code> </footer> diff --git a/tests/test_argus.py b/tests/test_argus.py index fed14cc..06d6430 100644 --- a/tests/test_argus.py +++ b/tests/test_argus.py @@ -8,7 +8,7 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, ROOT) -from argus import store, filter as flt, render, digest, providers, context +from argus import store, filter as flt, render, digest, providers, context, run as run_mod from argus.net import normalize_url from argus.collectors import library from argus.collectors.library import parse_dois @@ -444,3 +444,39 @@ def test_dashboard_excludes_library_items(tmp_path): html = open(render.render(conn, sample_cfg(), str(tmp_path / "index.html")), encoding="utf-8").read() assert "Public arxiv paper" in html assert "MY-LIBRARY-only paper" not in html # library items are digest-only + + +def test_master_switch_defaults_to_on_and_parses_yaml_falsey(): + """A config predating this switch must keep running.""" + assert run_mod.enabled({}) is True + assert run_mod.enabled({"enabled": True}) is True + for off in (False, "false", "False", "no", "off", "0", ""): + assert run_mod.enabled({"enabled": off}) is False, off + for on in (True, "true", "yes", "on"): + assert run_mod.enabled({"enabled": on}) is True, on + + +def test_disabled_sweep_does_nothing_but_force_overrides(tmp_path, capsys, monkeypatch): + """Off must mean no collection and no writes — not merely no commit.""" + cfg = tmp_path / "config.yaml" + cfg.write_text("enabled: false\nshow_threshold: 6\nhighlight_threshold: 8\n" + "tags: {methods: {label: M, color: '#000'}}\nscoring: {mode: keyword}\n" + "digest: {enabled: false}\nprompt: prompts/research.md\n", encoding="utf-8") + db = tmp_path / "out.db" + + called = [] + monkeypatch.setattr(run_mod, "collect_all", lambda *a, **k: called.append(1) or ([], [])) + + assert run_mod.main(["--config", str(cfg), "--db", str(db), "--stage", "collect"]) == 0 + assert "sweep disabled" in capsys.readouterr().out + assert called == [] # never collected + assert not db.exists() # never even opened the database + + assert run_mod.main(["--config", str(cfg), "--db", str(db), "--stage", "collect", "--force"]) == 0 + assert called == [1] # --force runs it + + +def test_shipped_config_has_the_switch_off_for_the_template(): + """The template must not sweep: whatever it collected would become the + starting data of every repository created from it.""" + assert run_mod.enabled(sample_cfg()) is False