From 5a50c8027ea5c4999b5a22222bc70c5ed2fea242 Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Thu, 20 Aug 2026 16:34:48 +0200 Subject: [PATCH] chore(bmad): migrate integration to codex Signed-off-by: Roland Salardon --- .../scripts/tests/test_pick_methods.py | 2 +- .../scripts/tests/test_lint_spine.py | 2 +- .../bmad-brainstorming/scripts/brain.py | 2 +- .../scripts/tests/test_brain.py | 2 +- .../scripts/tests/test_resolve_personas.py | 8 +- .../scripts/tests/test_resolve_party.py | 2 +- .../scripts/git_evidence.py | 2 +- .../scripts/sprint_status.py | 17 +- .../scripts/tests/test_sprint_status.py | 8 +- .../scripts/sprint_plan.py | 13 +- .../commands/bmad-advanced-elicitation.md | 5 - .opencode/commands/bmad-agent-analyst.md | 5 - .opencode/commands/bmad-agent-architect.md | 5 - .opencode/commands/bmad-agent-dev.md | 5 - .opencode/commands/bmad-agent-pm.md | 5 - .opencode/commands/bmad-agent-ux-designer.md | 5 - .opencode/commands/bmad-architecture.md | 5 - .opencode/commands/bmad-brainstorming.md | 5 - .opencode/commands/bmad-build-auto.md | 5 - .opencode/commands/bmad-build.md | 5 - .opencode/commands/bmad-checkpoint-preview.md | 5 - .opencode/commands/bmad-code-review.md | 5 - .opencode/commands/bmad-correct-course.md | 5 - .../commands/bmad-create-architecture.md | 5 - .../commands/bmad-create-epics-and-stories.md | 5 - .opencode/commands/bmad-create-prd.md | 5 - .opencode/commands/bmad-create-story.md | 5 - .opencode/commands/bmad-customize.md | 5 - .opencode/commands/bmad-deep-recon.md | 5 - .opencode/commands/bmad-dev-auto.md | 5 - .opencode/commands/bmad-dev-story.md | 5 - .opencode/commands/bmad-document-project.md | 5 - .opencode/commands/bmad-domain-research.md | 5 - .opencode/commands/bmad-edit-prd.md | 5 - .../commands/bmad-editorial-review-prose.md | 5 - .../bmad-editorial-review-structure.md | 5 - .opencode/commands/bmad-editorial-review.md | 5 - .opencode/commands/bmad-forge-idea.md | 5 - .../commands/bmad-generate-project-context.md | 5 - .opencode/commands/bmad-help.md | 5 - .opencode/commands/bmad-market-research.md | 5 - .opencode/commands/bmad-party-mode.md | 5 - .opencode/commands/bmad-prd.md | 5 - .opencode/commands/bmad-prfaq.md | 5 - .opencode/commands/bmad-product-brief.md | 5 - .opencode/commands/bmad-project-context.md | 5 - .../commands/bmad-qa-generate-e2e-tests.md | 5 - .opencode/commands/bmad-quick-dev.md | 5 - .opencode/commands/bmad-retrospective.md | 5 - .../bmad-review-adversarial-general.md | 5 - .../commands/bmad-review-edge-case-hunter.md | 5 - .../commands/bmad-review-verification-gap.md | 5 - .opencode/commands/bmad-review.md | 5 - .opencode/commands/bmad-spec.md | 5 - .opencode/commands/bmad-sprint-planning.md | 5 - .opencode/commands/bmad-sprint-status.md | 5 - .opencode/commands/bmad-technical-research.md | 5 - .opencode/commands/bmad-ux.md | 5 - .opencode/commands/bmad-validate-prd.md | 5 - AGENTS.md | 25 +- AUDIT_COMPLET.md | 6 +- BACKLOG.md | 5 + SESSION.md | 4 + _bmad/_config/files-manifest.csv | 8 +- _bmad/_config/manifest.yaml | 8 +- _bmad/bmm/config.yaml | 4 +- _bmad/config.toml | 2 +- _bmad/core/config.yaml | 4 +- _bmad/scripts/config_utils.py | 3 +- advisor-plans/README.md | 3 + docs/ROADMAP.md | 14 +- .../agentic/phase4-bmad-cleanup-2026-08-20.md | 88 +++++ docs/supermemory-export.md | 328 ------------------ opencode.json | 28 -- plans/README.md | 4 + pyproject.toml | 1 - tests/scripts/test_bmad_framework.py | 79 ++++- 77 files changed, 249 insertions(+), 668 deletions(-) delete mode 100644 .opencode/commands/bmad-advanced-elicitation.md delete mode 100644 .opencode/commands/bmad-agent-analyst.md delete mode 100644 .opencode/commands/bmad-agent-architect.md delete mode 100644 .opencode/commands/bmad-agent-dev.md delete mode 100644 .opencode/commands/bmad-agent-pm.md delete mode 100644 .opencode/commands/bmad-agent-ux-designer.md delete mode 100644 .opencode/commands/bmad-architecture.md delete mode 100644 .opencode/commands/bmad-brainstorming.md delete mode 100644 .opencode/commands/bmad-build-auto.md delete mode 100644 .opencode/commands/bmad-build.md delete mode 100644 .opencode/commands/bmad-checkpoint-preview.md delete mode 100644 .opencode/commands/bmad-code-review.md delete mode 100644 .opencode/commands/bmad-correct-course.md delete mode 100644 .opencode/commands/bmad-create-architecture.md delete mode 100644 .opencode/commands/bmad-create-epics-and-stories.md delete mode 100644 .opencode/commands/bmad-create-prd.md delete mode 100644 .opencode/commands/bmad-create-story.md delete mode 100644 .opencode/commands/bmad-customize.md delete mode 100644 .opencode/commands/bmad-deep-recon.md delete mode 100644 .opencode/commands/bmad-dev-auto.md delete mode 100644 .opencode/commands/bmad-dev-story.md delete mode 100644 .opencode/commands/bmad-document-project.md delete mode 100644 .opencode/commands/bmad-domain-research.md delete mode 100644 .opencode/commands/bmad-edit-prd.md delete mode 100644 .opencode/commands/bmad-editorial-review-prose.md delete mode 100644 .opencode/commands/bmad-editorial-review-structure.md delete mode 100644 .opencode/commands/bmad-editorial-review.md delete mode 100644 .opencode/commands/bmad-forge-idea.md delete mode 100644 .opencode/commands/bmad-generate-project-context.md delete mode 100644 .opencode/commands/bmad-help.md delete mode 100644 .opencode/commands/bmad-market-research.md delete mode 100644 .opencode/commands/bmad-party-mode.md delete mode 100644 .opencode/commands/bmad-prd.md delete mode 100644 .opencode/commands/bmad-prfaq.md delete mode 100644 .opencode/commands/bmad-product-brief.md delete mode 100644 .opencode/commands/bmad-project-context.md delete mode 100644 .opencode/commands/bmad-qa-generate-e2e-tests.md delete mode 100644 .opencode/commands/bmad-quick-dev.md delete mode 100644 .opencode/commands/bmad-retrospective.md delete mode 100644 .opencode/commands/bmad-review-adversarial-general.md delete mode 100644 .opencode/commands/bmad-review-edge-case-hunter.md delete mode 100644 .opencode/commands/bmad-review-verification-gap.md delete mode 100644 .opencode/commands/bmad-review.md delete mode 100644 .opencode/commands/bmad-spec.md delete mode 100644 .opencode/commands/bmad-sprint-planning.md delete mode 100644 .opencode/commands/bmad-sprint-status.md delete mode 100644 .opencode/commands/bmad-technical-research.md delete mode 100644 .opencode/commands/bmad-ux.md delete mode 100644 .opencode/commands/bmad-validate-prd.md create mode 100644 docs/agentic/phase4-bmad-cleanup-2026-08-20.md delete mode 100644 docs/supermemory-export.md delete mode 100644 opencode.json diff --git a/.agents/skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py b/.agents/skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py index 4b80142a..480f3cf1 100644 --- a/.agents/skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py +++ b/.agents/skills/bmad-advanced-elicitation/scripts/tests/test_pick_methods.py @@ -15,7 +15,7 @@ import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) -import pick_methods +import pick_methods # noqa: E402 CSV = """num,category,method_name,description,output_pattern 1,risk,Pre-mortem Analysis,Imagine future failure then work backwards,failure → causes → prevention diff --git a/.agents/skills/bmad-architecture/scripts/tests/test_lint_spine.py b/.agents/skills/bmad-architecture/scripts/tests/test_lint_spine.py index 8b1f7fca..55cf7482 100644 --- a/.agents/skills/bmad-architecture/scripts/tests/test_lint_spine.py +++ b/.agents/skills/bmad-architecture/scripts/tests/test_lint_spine.py @@ -123,7 +123,7 @@ def test_placeholder_version_caught(): def test_no_stack_section_ok(): - text = CLEAN.split("## Stack", maxsplit=1)[0] + text = CLEAN.split("## Stack")[0] result = lint_spine.lint(text) assert "version_pin" not in cats(result) diff --git a/.agents/skills/bmad-brainstorming/scripts/brain.py b/.agents/skills/bmad-brainstorming/scripts/brain.py index 08e383b7..1028cf6e 100644 --- a/.agents/skills/bmad-brainstorming/scripts/brain.py +++ b/.agents/skills/bmad-brainstorming/scripts/brain.py @@ -215,7 +215,7 @@ def _hsl_hex(deg: int, s: float, lt: float) -> str: import colorsys r, g, b = colorsys.hls_to_rgb((deg % 360) / 360, lt, s) - return f"#{round(r * 255):02x}{round(g * 255):02x}{round(b * 255):02x}" + return "#%02x%02x%02x" % (round(r * 255), round(g * 255), round(b * 255)) def category_style(cat: str) -> tuple[str, str]: diff --git a/.agents/skills/bmad-brainstorming/scripts/tests/test_brain.py b/.agents/skills/bmad-brainstorming/scripts/tests/test_brain.py index bea51aff..329a6a5f 100644 --- a/.agents/skills/bmad-brainstorming/scripts/tests/test_brain.py +++ b/.agents/skills/bmad-brainstorming/scripts/tests/test_brain.py @@ -10,7 +10,7 @@ import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) -import brain +import brain # noqa: E402 CSV = """category,technique_name,description,detail collaborative,Yes And Building,Build on every idea with "yes and" to keep momentum, diff --git a/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py b/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py index 556211ab..4867b0dc 100644 --- a/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py +++ b/.agents/skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py @@ -9,7 +9,7 @@ from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) -import resolve_personas as rp +import resolve_personas as rp # noqa: E402 AGENTS = { "bmad-agent-analyst": {"name": "Mary", "icon": "📊", "title": "Analyst"}, @@ -43,7 +43,7 @@ def test_pure_custom_member_stays_out_of_default_room(self): self.assertEqual(pool["morpheus"]["persona"], "riddles") def test_custom_override_lands_on_installed_slot_not_a_new_face(self): - pool, _, _installed, custom = rp.build_pool( + pool, _, installed, custom = rp.build_pool( AGENTS, [{"code": "analyst", "name": "Mary-Custom", "persona": "p"}]) self.assertNotIn("analyst", pool) self.assertEqual(custom, []) # an override is not a new face @@ -69,7 +69,7 @@ def test_brief_carries_model_and_capabilities(self): self.assertEqual(brief["capabilities"], ["x"]) def test_non_list_party_members_is_safe(self): - pool, _, _installed, custom = rp.build_pool(AGENTS, "not-a-list") + pool, _, installed, custom = rp.build_pool(AGENTS, "not-a-list") self.assertEqual(custom, []) self.assertEqual(set(pool), {"bmad-agent-analyst", "bmad-agent-pm"}) @@ -119,7 +119,7 @@ class TestOverrideMergeFallback(unittest.TestCase): """When party-mode isn't installed, user override TOMLs are read directly.""" def test_arrays_append_scalars_override(self): - import tempfile + import tempfile, os with tempfile.TemporaryDirectory() as d: custom = Path(d) / "_bmad" / "custom" custom.mkdir(parents=True) diff --git a/.agents/skills/bmad-party-mode/scripts/tests/test_resolve_party.py b/.agents/skills/bmad-party-mode/scripts/tests/test_resolve_party.py index f5032ec5..43aaa90c 100644 --- a/.agents/skills/bmad-party-mode/scripts/tests/test_resolve_party.py +++ b/.agents/skills/bmad-party-mode/scripts/tests/test_resolve_party.py @@ -9,7 +9,7 @@ from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) -import resolve_party as rp +import resolve_party as rp # noqa: E402 AGENTS = { "bmad-agent-analyst": {"name": "Mary", "icon": "📊", "title": "Analyst"}, diff --git a/.agents/skills/bmad-retrospective/scripts/git_evidence.py b/.agents/skills/bmad-retrospective/scripts/git_evidence.py index 5803250a..4ff81162 100644 --- a/.agents/skills/bmad-retrospective/scripts/git_evidence.py +++ b/.agents/skills/bmad-retrospective/scripts/git_evidence.py @@ -105,7 +105,7 @@ def _git_log(repo, extra_args, rng): errors="surrogateescape", env={k: v for k, v in os.environ.items() if not k.startswith("GIT_")}, ) - except Exception as exc: + except Exception as exc: # noqa: BLE001 _emit({"ok": False, "error": str(exc)}, 1) if proc.returncode != 0: diff --git a/.agents/skills/bmad-retrospective/scripts/sprint_status.py b/.agents/skills/bmad-retrospective/scripts/sprint_status.py index 9472b647..f41171be 100644 --- a/.agents/skills/bmad-retrospective/scripts/sprint_status.py +++ b/.agents/skills/bmad-retrospective/scripts/sprint_status.py @@ -11,7 +11,6 @@ """ import argparse -import contextlib import hashlib import io import json @@ -50,7 +49,7 @@ def _load_yaml(path): # file. utf-8 is ruamel's current default, but the file is read back as # utf-8 unconditionally, so state it rather than inherit it. yaml.encoding = "utf-8" - with open(path, encoding="utf-8") as fh: + with open(path, "r", encoding="utf-8") as fh: data = yaml.load(fh) return yaml, data @@ -172,7 +171,7 @@ def _load_document(path, restored=None): _emit_error(f"{path} is not valid UTF-8: {exc}", 1, restored) except OSError as exc: _emit_error(str(exc), 1, restored) - except Exception as exc: + except Exception as exc: # noqa: BLE001 - report any parse error as JSON _emit_error(str(exc), 1, restored) if data is not None and not isinstance(data, Mapping): @@ -232,8 +231,10 @@ def _atomic_write(path, payload, mode=None): os.chmod(tmp_path, mode) os.replace(tmp_path, path) except BaseException: - with contextlib.suppress(OSError): + try: os.unlink(tmp_path) + except OSError: + pass raise # The directory sync sits outside the try because once os.replace has # returned, the new bytes ARE the file: a failure past that point must not @@ -558,7 +559,7 @@ def cmd_update(args): # 7. Serialize, then swap the file atomically. try: _atomic_write(args.file, _dump_bytes(yaml, data), original_mode) - except Exception as exc: + except Exception as exc: # noqa: BLE001 # The target is only ever touched by the final rename, so if the write # raised, the original is still on disk byte-for-byte. Calling _restore # here would rewrite a file that was never modified -- the one write in @@ -572,7 +573,7 @@ def _fail(msg): try: _, reloaded = _load_yaml(args.file) - except Exception as exc: + except Exception as exc: # noqa: BLE001 _fail(f"re-parse failed after write: {exc}") if reloaded is None: @@ -613,7 +614,7 @@ def _fail(msg): ) try: - with open(args.file, encoding="utf-8") as fh: + with open(args.file, "r", encoding="utf-8") as fh: new_text = fh.read() except (OSError, UnicodeDecodeError) as exc: _fail(f"re-read failed after write: {exc}") @@ -651,7 +652,7 @@ def _restore(path, original_bytes, mode=None): try: _atomic_write(path, original_bytes, mode) return True - except Exception as exc: + except Exception as exc: # noqa: BLE001 - best-effort restore sys.stderr.write(f"restore failed: {exc}\n") return False diff --git a/.agents/skills/bmad-retrospective/scripts/tests/test_sprint_status.py b/.agents/skills/bmad-retrospective/scripts/tests/test_sprint_status.py index f2460d2c..590215f5 100644 --- a/.agents/skills/bmad-retrospective/scripts/tests/test_sprint_status.py +++ b/.agents/skills/bmad-retrospective/scripts/tests/test_sprint_status.py @@ -143,7 +143,7 @@ def _write_action_fixture(tmp_path): def _load(path): yaml = YAML(typ="rt") - with open(path, encoding="utf-8") as fh: + with open(path, "r", encoding="utf-8") as fh: return yaml.load(fh) @@ -650,7 +650,7 @@ def test_template_round_trip_changes_only_last_updated(tmp_path): before = source.splitlines() after = target.read_text(encoding="utf-8").splitlines() assert len(before) == len(after) - changed = [(b, a) for b, a in zip(before, after, strict=False) if b != a] + changed = [(b, a) for b, a in zip(before, after) if b != a] assert len(changed) == 1, changed assert changed[0][1] == "last_updated: 01-01-2026 09:00" # The pre-existing action item keeps its 2-space sequence indent. @@ -1096,7 +1096,7 @@ def test_set_action_status_changes_exactly_one_line(tmp_path): before = ACTION_FIXTURE.splitlines() after = target.read_text(encoding="utf-8").splitlines() assert len(before) == len(after) - changed = [(b, a) for b, a in zip(before, after, strict=False) if b != a] + changed = [(b, a) for b, a in zip(before, after) if b != a] assert changed == [(' status: "open"', ' status: "done"')], changed @@ -1497,7 +1497,7 @@ def test_status_write_preserves_every_scalar_style(tmp_path): before = STYLE_FIXTURE.splitlines() after = target.read_text(encoding="utf-8").splitlines() assert len(before) == len(after) - changed = [(b, a) for b, a in zip(before, after, strict=False) if b != a] + changed = [(b, a) for b, a in zip(before, after) if b != a] assert changed == [ (' status: "open"', ' status: "done"'), (" status: 'open'", " status: 'done'"), diff --git a/.agents/skills/bmad-sprint-planning/scripts/sprint_plan.py b/.agents/skills/bmad-sprint-planning/scripts/sprint_plan.py index 21b5b0da..bc486ba8 100644 --- a/.agents/skills/bmad-sprint-planning/scripts/sprint_plan.py +++ b/.agents/skills/bmad-sprint-planning/scripts/sprint_plan.py @@ -29,7 +29,6 @@ """ import argparse -import contextlib import hashlib import io import json @@ -228,7 +227,7 @@ def _load_existing(path): if not Path(path).exists(): return yaml, None try: - with open(path, encoding="utf-8") as fh: + with io.open(path, "r", encoding="utf-8") as fh: data = yaml.load(fh) except Exception as exc: _fail(f"existing status file is not valid YAML: {exc}", status_file=str(path)) @@ -348,8 +347,10 @@ def _atomic_write(path, payload, mode=None): os.chmod(tmp, mode) os.replace(tmp, path) except BaseException: - with contextlib.suppress(OSError): + try: os.unlink(tmp) + except OSError: + pass raise @@ -447,9 +448,9 @@ def _meta(field, arg_value, default): payload = _dump_bytes(yaml, doc) _atomic_write(args.status_file, payload, original_mode) verify_yaml = _make_yaml() - with open(args.status_file, encoding="utf-8") as fh: + with io.open(args.status_file, "r", encoding="utf-8") as fh: reread = verify_yaml.load(fh) - if dict(reread.get("development_status") or {}) != dict(dev.items()): + if dict(reread.get("development_status") or {}) != {k: v for k, v in dev.items()}: raise ValueError("development_status mismatch after write") for field in ("generated", "last_updated", "project"): if str(reread.get(field)) != str(doc[field]): @@ -604,7 +605,7 @@ def cmd_validate(args): return yaml = _make_yaml() try: - with open(args.status_file, encoding="utf-8") as fh: + with io.open(args.status_file, "r", encoding="utf-8") as fh: data = yaml.load(fh) except Exception as exc: print(json.dumps({ diff --git a/.opencode/commands/bmad-advanced-elicitation.md b/.opencode/commands/bmad-advanced-elicitation.md deleted file mode 100644 index a8983e82..00000000 --- a/.opencode/commands/bmad-advanced-elicitation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Push the LLM to reconsider, refine, and improve its recent output. Use when user asks for deeper critique or mentions a known deeper critique method, e.g. socratic, first principles, pre-mortem, red team. ---- - -@skills/bmad-advanced-elicitation diff --git a/.opencode/commands/bmad-agent-analyst.md b/.opencode/commands/bmad-agent-analyst.md deleted file mode 100644 index ce9491c6..00000000 --- a/.opencode/commands/bmad-agent-analyst.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Strategic business analyst and requirements expert. Use when the user asks to talk to Mary or requests the business analyst. ---- - -@skills/bmad-agent-analyst diff --git a/.opencode/commands/bmad-agent-architect.md b/.opencode/commands/bmad-agent-architect.md deleted file mode 100644 index 95d0dfda..00000000 --- a/.opencode/commands/bmad-agent-architect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: System architect and technical design leader. Use when the user asks to talk to Winston or requests the architect. ---- - -@skills/bmad-agent-architect diff --git a/.opencode/commands/bmad-agent-dev.md b/.opencode/commands/bmad-agent-dev.md deleted file mode 100644 index 3b7467b6..00000000 --- a/.opencode/commands/bmad-agent-dev.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Senior software engineer for story execution and code implementation. Use when the user asks to talk to Amelia or requests the developer agent. ---- - -@skills/bmad-agent-dev diff --git a/.opencode/commands/bmad-agent-pm.md b/.opencode/commands/bmad-agent-pm.md deleted file mode 100644 index fcb21bbe..00000000 --- a/.opencode/commands/bmad-agent-pm.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Product manager for PRD creation and requirements discovery. Use when the user asks to talk to John or requests the product manager. ---- - -@skills/bmad-agent-pm diff --git a/.opencode/commands/bmad-agent-ux-designer.md b/.opencode/commands/bmad-agent-ux-designer.md deleted file mode 100644 index 2134f67a..00000000 --- a/.opencode/commands/bmad-agent-ux-designer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: UX designer and UI specialist. Use when the user asks to talk to Sally or requests the UX designer. ---- - -@skills/bmad-agent-ux-designer diff --git a/.opencode/commands/bmad-architecture.md b/.opencode/commands/bmad-architecture.md deleted file mode 100644 index 6788181f..00000000 --- a/.opencode/commands/bmad-architecture.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Produce the architecture: a lean spine of invariants that keeps everything built from it consistent, projected into whatever format the work needs. Use when the user says \"create the architecture\", \"create technical architecture\", \"architecture spine\", or \"create a solution design\"." ---- - -@skills/bmad-architecture diff --git a/.opencode/commands/bmad-brainstorming.md b/.opencode/commands/bmad-brainstorming.md deleted file mode 100644 index c895bcba..00000000 --- a/.opencode/commands/bmad-brainstorming.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Facilitate a brainstorming session using diverse creative techniques. Use when the user says 'help me brainstorm' or 'help me ideate'." ---- - -@skills/bmad-brainstorming diff --git a/.opencode/commands/bmad-build-auto.md b/.opencode/commands/bmad-build-auto.md deleted file mode 100644 index dce314a6..00000000 --- a/.opencode/commands/bmad-build-auto.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: One iteration of an unattended development loop. Use when invoked by name. ---- - -@skills/bmad-build-auto diff --git a/.opencode/commands/bmad-build.md b/.opencode/commands/bmad-build.md deleted file mode 100644 index 168054cd..00000000 --- a/.opencode/commands/bmad-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Implements any user intent, requirement, story, bug fix or change request by producing clean working code artifacts that follow the project's existing architecture, patterns and conventions. Use when the user wants to build, fix, tweak, refactor, add or modify any code, component or feature." ---- - -@skills/bmad-build diff --git a/.opencode/commands/bmad-checkpoint-preview.md b/.opencode/commands/bmad-checkpoint-preview.md deleted file mode 100644 index 298ce243..00000000 --- a/.opencode/commands/bmad-checkpoint-preview.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "LLM-assisted human-in-the-loop review. Make sense of a change, focus attention where it matters, test. Use when the user says \"checkpoint\", \"human review\", or \"walk me through this change\"." ---- - -@skills/bmad-checkpoint-preview diff --git a/.opencode/commands/bmad-code-review.md b/.opencode/commands/bmad-code-review.md deleted file mode 100644 index 84763995..00000000 --- a/.opencode/commands/bmad-code-review.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Adversarial code review using parallel review layers and structured triage. Use when the user says \"run code review\" or \"review this code\"" ---- - -@skills/bmad-code-review diff --git a/.opencode/commands/bmad-correct-course.md b/.opencode/commands/bmad-correct-course.md deleted file mode 100644 index 5f0fcb21..00000000 --- a/.opencode/commands/bmad-correct-course.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Manage significant changes during sprint execution. Use when the user says \"correct course\" or \"propose sprint change\"" ---- - -@skills/bmad-correct-course diff --git a/.opencode/commands/bmad-create-architecture.md b/.opencode/commands/bmad-create-architecture.md deleted file mode 100644 index 565e1fc3..00000000 --- a/.opencode/commands/bmad-create-architecture.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-architecture (create intent). ---- - -@skills/bmad-create-architecture diff --git a/.opencode/commands/bmad-create-epics-and-stories.md b/.opencode/commands/bmad-create-epics-and-stories.md deleted file mode 100644 index 29e725d5..00000000 --- a/.opencode/commands/bmad-create-epics-and-stories.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Break requirements into epics and user stories. Use when the user says \"create the epics and stories list\"" ---- - -@skills/bmad-create-epics-and-stories diff --git a/.opencode/commands/bmad-create-prd.md b/.opencode/commands/bmad-create-prd.md deleted file mode 100644 index 808f1f66..00000000 --- a/.opencode/commands/bmad-create-prd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-prd (create intent). ---- - -@skills/bmad-create-prd diff --git a/.opencode/commands/bmad-create-story.md b/.opencode/commands/bmad-create-story.md deleted file mode 100644 index e2963ce8..00000000 --- a/.opencode/commands/bmad-create-story.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated: `bmad-build` is now the official implementation method. Only use this when explicitly invoked by name." ---- - -@skills/bmad-create-story diff --git a/.opencode/commands/bmad-customize.md b/.opencode/commands/bmad-customize.md deleted file mode 100644 index 58a235d8..00000000 --- a/.opencode/commands/bmad-customize.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Authors and updates customization overrides for installed BMad skills. Use when the user says 'customize bmad', 'override a skill', 'change agent behavior', or 'customize a workflow'." ---- - -@skills/bmad-customize diff --git a/.opencode/commands/bmad-deep-recon.md b/.opencode/commands/bmad-deep-recon.md deleted file mode 100644 index fc91d16d..00000000 --- a/.opencode/commands/bmad-deep-recon.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Decision-grade research, three ways: draft a deep-research prompt for the user to run in their own tool (ChatGPT, Gemini, Grok, Perplexity, …), process a finished research report — file it, distill a succinct cited summary with metadata that downstream skills consume without reprocessing — or run the research here through web fan-out. Shipped type packs: market, domain, technical, competitive, user-voice, academic-lit — plus a select shape for choose-between decisions and custom types via overrides. Use when the user says \"deep recon\", \"research this\", \"draft a research prompt\", \"process this research report\", \"market research\", \"domain research\", \"technical research\", \"competitor research\", \"literature review\", or \"help me choose between\"." ---- - -@skills/bmad-deep-recon diff --git a/.opencode/commands/bmad-dev-auto.md b/.opencode/commands/bmad-dev-auto.md deleted file mode 100644 index d0db9a4e..00000000 --- a/.opencode/commands/bmad-dev-auto.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated: forwards to bmad-build-auto. Do not use unless invoked by name." ---- - -@skills/bmad-dev-auto diff --git a/.opencode/commands/bmad-dev-story.md b/.opencode/commands/bmad-dev-story.md deleted file mode 100644 index ae46967e..00000000 --- a/.opencode/commands/bmad-dev-story.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated: `bmad-build` is now the official implementation method. Only use this when explicitly invoked by name." ---- - -@skills/bmad-dev-story diff --git a/.opencode/commands/bmad-document-project.md b/.opencode/commands/bmad-document-project.md deleted file mode 100644 index ffa11bf5..00000000 --- a/.opencode/commands/bmad-document-project.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated — forwards to bmad-project-context. Use when the user says \"document this project\" or \"generate project docs\"" ---- - -@skills/bmad-document-project diff --git a/.opencode/commands/bmad-domain-research.md b/.opencode/commands/bmad-domain-research.md deleted file mode 100644 index 32577907..00000000 --- a/.opencode/commands/bmad-domain-research.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-deep-recon (domain type). ---- - -@skills/bmad-domain-research diff --git a/.opencode/commands/bmad-edit-prd.md b/.opencode/commands/bmad-edit-prd.md deleted file mode 100644 index ab54b2c0..00000000 --- a/.opencode/commands/bmad-edit-prd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-prd (update intent). ---- - -@skills/bmad-edit-prd diff --git a/.opencode/commands/bmad-editorial-review-prose.md b/.opencode/commands/bmad-editorial-review-prose.md deleted file mode 100644 index b679974e..00000000 --- a/.opencode/commands/bmad-editorial-review-prose.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-editorial-review-prose diff --git a/.opencode/commands/bmad-editorial-review-structure.md b/.opencode/commands/bmad-editorial-review-structure.md deleted file mode 100644 index 148e01bb..00000000 --- a/.opencode/commands/bmad-editorial-review-structure.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-editorial-review-structure diff --git a/.opencode/commands/bmad-editorial-review.md b/.opencode/commands/bmad-editorial-review.md deleted file mode 100644 index b82f96b3..00000000 --- a/.opencode/commands/bmad-editorial-review.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-editorial-review diff --git a/.opencode/commands/bmad-forge-idea.md b/.opencode/commands/bmad-forge-idea.md deleted file mode 100644 index 572fd77c..00000000 --- a/.opencode/commands/bmad-forge-idea.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Pressure-test an idea through persona-driven interrogation until it hardens, proves out, or dies cheaply. Use when the user says 'forge an idea', 'pressure-test this idea', 'stress-test my thinking', or 'harden this idea'." ---- - -@skills/bmad-forge-idea diff --git a/.opencode/commands/bmad-generate-project-context.md b/.opencode/commands/bmad-generate-project-context.md deleted file mode 100644 index a1f659b4..00000000 --- a/.opencode/commands/bmad-generate-project-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated — forwards to bmad-project-context. Use when the user says \"generate project context\" or \"create project context\"" ---- - -@skills/bmad-generate-project-context diff --git a/.opencode/commands/bmad-help.md b/.opencode/commands/bmad-help.md deleted file mode 100644 index aa17c4a4..00000000 --- a/.opencode/commands/bmad-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Analyzes current state and user query to answer BMad questions or recommend the next skill(s) to use. Use when user asks for help, bmad help, what to do next, or what to start with in BMad. ---- - -@skills/bmad-help diff --git a/.opencode/commands/bmad-market-research.md b/.opencode/commands/bmad-market-research.md deleted file mode 100644 index c4f4e956..00000000 --- a/.opencode/commands/bmad-market-research.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-deep-recon (market type). ---- - -@skills/bmad-market-research diff --git a/.opencode/commands/bmad-party-mode.md b/.opencode/commands/bmad-party-mode.md deleted file mode 100644 index 293666a0..00000000 --- a/.opencode/commands/bmad-party-mode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Orchestrates lively group discussions between installed BMAD agents or custom personas, and helps author custom parties. Use when the user requests party mode, a roundtable, or multiple agent perspectives — or wants to create/configure a party, define personas, or build an AI focus-group panel. ---- - -@skills/bmad-party-mode diff --git a/.opencode/commands/bmad-prd.md b/.opencode/commands/bmad-prd.md deleted file mode 100644 index c25419e5..00000000 --- a/.opencode/commands/bmad-prd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Create, update, or validate a PRD. Use when the user wants help producing, editing, or validating a PRD. ---- - -@skills/bmad-prd diff --git a/.opencode/commands/bmad-prfaq.md b/.opencode/commands/bmad-prfaq.md deleted file mode 100644 index e40b886e..00000000 --- a/.opencode/commands/bmad-prfaq.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Working Backwards PRFAQ challenge that stress-tests a product concept customer-first. Use when the user requests to 'create a PRFAQ', 'work backwards', or 'run the PRFAQ challenge'." ---- - -@skills/bmad-prfaq diff --git a/.opencode/commands/bmad-product-brief.md b/.opencode/commands/bmad-product-brief.md deleted file mode 100644 index b6be35db..00000000 --- a/.opencode/commands/bmad-product-brief.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Create, update, or validate a product brief. Use when the user wants help producing, editing, or validating a brief. ---- - -@skills/bmad-product-brief diff --git a/.opencode/commands/bmad-project-context.md b/.opencode/commands/bmad-project-context.md deleted file mode 100644 index f062280e..00000000 --- a/.opencode/commands/bmad-project-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Set up, refresh, or audit a repository's agent instructions (the AGENTS.md block) so AI agents work well in that repo. Also records observed agent mistakes as pitfall lines. Must be invoked by name." ---- - -@skills/bmad-project-context diff --git a/.opencode/commands/bmad-qa-generate-e2e-tests.md b/.opencode/commands/bmad-qa-generate-e2e-tests.md deleted file mode 100644 index 811116d5..00000000 --- a/.opencode/commands/bmad-qa-generate-e2e-tests.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Generate end to end automated tests for existing features. Use when the user says \"create qa automated tests for [feature]\"" ---- - -@skills/bmad-qa-generate-e2e-tests diff --git a/.opencode/commands/bmad-quick-dev.md b/.opencode/commands/bmad-quick-dev.md deleted file mode 100644 index 90f5a949..00000000 --- a/.opencode/commands/bmad-quick-dev.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Deprecated: forwards to bmad-build. Do not use unless invoked by name." ---- - -@skills/bmad-quick-dev diff --git a/.opencode/commands/bmad-retrospective.md b/.opencode/commands/bmad-retrospective.md deleted file mode 100644 index c1ed7d8e..00000000 --- a/.opencode/commands/bmad-retrospective.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Evidence-based epic retrospective — collect what the epic produced, verify findings against sources, render an acceptance verdict. Use when the user says \"run a retrospective\" or \"lets retro the epic [epic]\". Supports -H/--headless." ---- - -@skills/bmad-retrospective diff --git a/.opencode/commands/bmad-review-adversarial-general.md b/.opencode/commands/bmad-review-adversarial-general.md deleted file mode 100644 index 4f8f140e..00000000 --- a/.opencode/commands/bmad-review-adversarial-general.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-review-adversarial-general diff --git a/.opencode/commands/bmad-review-edge-case-hunter.md b/.opencode/commands/bmad-review-edge-case-hunter.md deleted file mode 100644 index 40358def..00000000 --- a/.opencode/commands/bmad-review-edge-case-hunter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-review-edge-case-hunter diff --git a/.opencode/commands/bmad-review-verification-gap.md b/.opencode/commands/bmad-review-verification-gap.md deleted file mode 100644 index e2a61e07..00000000 --- a/.opencode/commands/bmad-review-verification-gap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-review. ---- - -@skills/bmad-review-verification-gap diff --git a/.opencode/commands/bmad-review.md b/.opencode/commands/bmad-review.md deleted file mode 100644 index f2cb87f6..00000000 --- a/.opencode/commands/bmad-review.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Multi-lens review over any diff, doc, spec, or artifact — whichever installed lenses fit the content, run singly or together. Shipped lenses include adversarial, edge-case, verification-gap, structure, and prose. Use when the user says \"review this\", \"critical review\", \"editorial review\", \"hunt edge cases\", \"review the structure\", or \"review the prose\"." ---- - -@skills/bmad-review diff --git a/.opencode/commands/bmad-spec.md b/.opencode/commands/bmad-spec.md deleted file mode 100644 index 23c3916a..00000000 --- a/.opencode/commands/bmad-spec.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Distill any intent input into the SPEC kernel + companions — the canonical, preservation-validated machine contract for downstream work. Use when the user says \"create a spec\", \"distill this into a spec\", \"validate this spec\", \"update the spec\", or \"break this into stories\"." ---- - -@skills/bmad-spec diff --git a/.opencode/commands/bmad-sprint-planning.md b/.opencode/commands/bmad-sprint-planning.md deleted file mode 100644 index 078ed232..00000000 --- a/.opencode/commands/bmad-sprint-planning.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Gate planning readiness, generate sprint status tracking from epics, summarize sprint progress, and validate or repair the tracking file. Use when the user says \"run sprint planning\", \"generate sprint plan\", \"check implementation readiness\", \"show sprint status\", \"validate sprint status\", or \"fix sprint status\"" ---- - -@skills/bmad-sprint-planning diff --git a/.opencode/commands/bmad-sprint-status.md b/.opencode/commands/bmad-sprint-status.md deleted file mode 100644 index 29766ece..00000000 --- a/.opencode/commands/bmad-sprint-status.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-sprint-planning (status view). ---- - -@skills/bmad-sprint-status diff --git a/.opencode/commands/bmad-technical-research.md b/.opencode/commands/bmad-technical-research.md deleted file mode 100644 index 9990787b..00000000 --- a/.opencode/commands/bmad-technical-research.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-deep-recon (technical type). ---- - -@skills/bmad-technical-research diff --git a/.opencode/commands/bmad-ux.md b/.opencode/commands/bmad-ux.md deleted file mode 100644 index 6f031186..00000000 --- a/.opencode/commands/bmad-ux.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: "Plan UX patterns and design specifications. Use when the user says \"lets create UX design\" or \"create UX specifications\" or \"help me plan the UX\"" ---- - -@skills/bmad-ux diff --git a/.opencode/commands/bmad-validate-prd.md b/.opencode/commands/bmad-validate-prd.md deleted file mode 100644 index 477e3e39..00000000 --- a/.opencode/commands/bmad-validate-prd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: Deprecated — forwards to bmad-prd (validate intent). ---- - -@skills/bmad-validate-prd diff --git a/AGENTS.md b/AGENTS.md index a94037e5..6048f5d0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,21 +1,21 @@ # Règles de session — Gw2Analytics -## Compactions / résumés de session -À CHAQUE fin de session (ou à chaque compaction), sauvegarder le résumé complet de la session dans **supermemory** : +## Mémoire durable et confidentialité -- Espace actif par défaut (ne pas en créer d'autre). -- Format : titre `## PROJET Gw2Analytics — Résumé de session (YYYY-MM-DD)` puis sections : Objectif, État du travail (fait/en cours/bloqué), Next Move, Fichiers clés, Probes, Notes de décision. -- Toujours inclure les diffs de parité actuels (par joueur), les mappings EI identifiés, et les IDs/GUIDs en jeu. -- Utiliser `supermemory_add_memory` avec `action: "save"`. - -Ne PAS garder le résumé uniquement dans le contexte de session — il doit être persistant dans supermemory pour les sessions suivantes. +- Le dépôt est la mémoire durable : code/tests/CI pour le comportement livré, + SPEC acceptées pour le contrat à construire, ADR pour les décisions et + `docs/agentic/` pour les checkpoints opérationnels. +- Supermemory est un outil personnel optionnel ; il ne constitue ni une + dépendance, ni une source de vérité, ni une obligation de fin de session. +- `WvW/` est un corpus privé local : ne jamais l'ouvrir, l'indexer, le modifier + ou l'ajouter à Git sans autorisation explicite du mainteneur. ## Gw2Analytics -Plateforme d'analyse de combats WvW. Les contrats et conventions détaillés vivent dans `README.md`, `CONTRIBUTING.md` et `docs/`; la planification BMAD vit dans `_bmad-output/`. +Plateforme d'analyse de combats WvW. Les contrats et conventions détaillés vivent dans `README.md`, `CONTRIBUTING.md` et `docs/`; les SPEC BMAD acceptées vivent dans `_bmad-output/specs/`. ## Policy @@ -27,14 +27,15 @@ Plateforme d'analyse de combats WvW. Les contrats et conventions détaillés viv ## Where things are - Comparaison EI canonique: `libs/gw2_analytics/src/gw2_analytics/ei_compare.py`; pilotes et corpus local: `scripts/ei-parity/`. -- Décisions d'architecture acceptées: `docs/adr/`; contrat BMAD actif: `_bmad-output/specs/`. +- Décisions d'architecture acceptées: `docs/adr/`; contrat BMAD actif: `_bmad-output/specs/`; checkpoints opérationnels: `docs/agentic/`. +- Les roadmaps, backlogs, sessions et plans explicitement marqués historiques ne définissent pas la priorité. Au Level 1, une nouvelle priorité exige une proposition puis l'accord du mainteneur. ## Running and verifying - Exécuter les outils Python via `uv run`; une invocation Python nue contourne l'environnement du workspace. - Itérer avec les tests ciblés; la suite Python complète impose une couverture globale de 90 % et peut nécessiter les services Docker pour les tests d'intégration. -- Les skills BMAD vivent dans `.agents/skills/bmad-*` (chargés via `skills.paths` d'`opencode.json`) et le framework dans `_bmad/`. Le noyau (`resolve_config.py`, `resolve_customization.py`, `render_skill.py`, `memlog.py`) ne dépend que de la stdlib — vérifiable via `tests/scripts/test_bmad_framework.py`. -- opencode ne substitue aucune variable dans les skills (à la différence de Claude Code) : remplacer manuellement `{project-root}` par la racine du repo (`/home/roddy/Work/Gw2Analytics`) et `{skill-root}` par le répertoire du skill invoqué (le bloc « Base directory » de l'outil skill). +- Les skills BMAD canoniques vivent dans `.agents/skills/bmad-*` et sont intégrés à Codex. Le framework est dans `_bmad/`. Le noyau (`resolve_config.py`, `resolve_customization.py`, `render_skill.py`, `memlog.py`) ne dépend que de la stdlib — vérifiable via `tests/scripts/test_bmad_framework.py`. +- Régénérer une intégration BMAD par l'installeur officiel épinglé plutôt que modifier les fichiers gérés à la main. OpenCode n'est plus un harness actif ; tout fallback multi-provider exige une configuration et une validation distinctes. ## Conventions that differ from defaults diff --git a/AUDIT_COMPLET.md b/AUDIT_COMPLET.md index d1615c8f..593fbd31 100644 --- a/AUDIT_COMPLET.md +++ b/AUDIT_COMPLET.md @@ -1,5 +1,9 @@ # Audit d'Architecture Complet — Gw2Analytics +> **Historique — pas une source de vérité actuelle.** Audit daté du +> 2026-07-24, préservé pour la traçabilité. Toute décision doit être réévaluée +> contre le dépôt, les tests/CI, les ADR et les SPEC acceptées. + **Date :** 2026-07-24 **Profil :** Monorepo GW2 WvW Combat Analytics (Python 3.12 + FastAPI + Next.js + PostgreSQL) @@ -474,4 +478,4 @@ CREATE INDEX ix_fights_no_summary ON fights(id) WHERE id NOT IN (SELECT fight_id --- -*Rapport généré par audit automatisé — analyse basée sur 100+ fichiers inspectés dans le monorepo Gw2Analytics.* \ No newline at end of file +*Rapport généré par audit automatisé — analyse basée sur 100+ fichiers inspectés dans le monorepo Gw2Analytics.* diff --git a/BACKLOG.md b/BACKLOG.md index 30886c10..70ebdbcb 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -1,5 +1,10 @@ # Backlog — parser / Elite Insights parity +> **Historique — pas une source de priorité actuelle.** Ce score et ces pistes +> datent du 2026-08-07. Conserver comme provenance de parité, mais repartir du +> contrat accepté, du checkpoint courant et d'une mesure reproductible avant +> de sélectionner un travail. + Measured with `uv run python scripts/ei-parity/ei_diff.py` over the 35-log corpus. Setup and probes: `docs/ei-parity-workbench.md`. Findings so far: `docs/parser-audit-2026-07-31.md`. diff --git a/SESSION.md b/SESSION.md index f40eadea..ae3e2c5c 100644 --- a/SESSION.md +++ b/SESSION.md @@ -1,5 +1,9 @@ # Session log — Elite Insights parity +> **Historique — pas un état courant.** Ces notes conservent les décisions et +> probes passés ; elles ne doivent pas piloter une nouvelle priorité sans +> confirmation par le code, les tests, le corpus disponible et le mainteneur. + Newest first. Each entry records what moved, how it was confirmed, and what was ruled out, so a later pass does not retrace the same ground. diff --git a/_bmad/_config/files-manifest.csv b/_bmad/_config/files-manifest.csv index 88dfa16f..347b6ea4 100644 --- a/_bmad/_config/files-manifest.csv +++ b/_bmad/_config/files-manifest.csv @@ -1,5 +1,5 @@ type,name,module,path,hash -"yaml","manifest","_config","_config/manifest.yaml","4bcd9828ba8d518e5149ee89eccddd86c3a70e880a140077ab88b328563bf377" +"yaml","manifest","_config","_config/manifest.yaml","d0f3dcbca13c89285f878d95e3fd1c8f48610017573a1c0a8036df4f3b045ba2" "csv","module-help","bmm","bmm/module-help.csv","fe1f3c778d5d909d5858e0d13f2a7d4d18f40180de05a3c4fa7a5470dabeb945" "html","validation-report-template","bmm","bmm/plan/bmad-prd/assets/validation-report-template.html","a80becdd8205d2d7c18738855830b096172a496b96b5ca8a0820ec55c9bb8bf9" "html","validation-report-template","bmm","bmm/plan/bmad-ux/assets/validation-report-template.html","8656945636fabe96624f8ef8fce931b073b5aecbe42d490584c1d5c7f31e1353" @@ -173,10 +173,10 @@ type,name,module,path,hash "toml","customize","bmm","bmm/v6-shims/bmad-edit-prd/customize.toml","35cc2dfb3eda73a0ae4dc987cac58867b25c43ce5c5a1bf552e215826ede6c22" "toml","customize","bmm","bmm/v6-shims/bmad-sprint-status/customize.toml","96261fd227befaa4685b0a5091d3e85299d4ae8e4404176b42f5ef2e2fb501bd" "toml","customize","bmm","bmm/v6-shims/bmad-validate-prd/customize.toml","bfb3c8af5b81b2cdb9bb84f844f1b0dafc40d8c283effa6ad48db966b9446cef" -"yaml","config","bmm","bmm/config.yaml","e7c26107e9beba9015b9c3abb864d75ff9d6dd9a9eeb3ca71ded263ecc1e31ba" +"yaml","config","bmm","bmm/config.yaml","b871746851c3d5cb36e4754da2affbd852cf2e25451dd7e8f041984af6cd15d2" "yaml","sprint-status-template","bmm","bmm/plan/bmad-sprint-planning/sprint-status-template.yaml","64b1a937e1fe03b8b8d158e3b1caeb89e7d51692a56c16038e2af091decc553a" "yaml","sprint-status-template","bmm","bmm/ship/bmad-retrospective/scripts/tests/fixtures/sprint-status-template.yaml","64b1a937e1fe03b8b8d158e3b1caeb89e7d51692a56c16038e2af091decc553a" -"toml","config","config.toml","config.toml","a892a7cc790e962c5c86083cf5263f62d8125b1855b612dd871352a1c698dc5b" +"toml","config","config.toml","config.toml","bc63645aa55728cf92d645c2d096c872bd32e406f6ca41a1eec8f46e633f6a62" "toml","config.user","config.user.toml","config.user.toml","28cc23d548471dd6810e9d49902dd46fd0a95c22160b5541eb425b5fa49f7e96" "csv","brain-methods","core","core/bmad-brainstorming/assets/brain-methods.csv","fff112eabca1a9cb8b190f8314bc47678becc5782a2372e11c83daa0e33b6dfd" "csv","methods","core","core/bmad-advanced-elicitation/assets/methods.csv","d110ff5f076fb9421552b83692fde2c2d367734049169c7a55f7267a3dc7ef89" @@ -255,7 +255,7 @@ type,name,module,path,hash "toml","customize","core","core/bmad-party-mode/customize.toml","9c6ee33cd7fdd80e4adf514c3d54636d933d5250c2ddd78041c6cfe73b745bb0" "toml","customize","core","core/bmad-review/customize.toml","38470c888a809ee030dc11d38868bb1ac5c1d547f06d218b711be5df53385c00" "toml","customize","core","core/v6-shims/bmad-editorial-review/customize.toml","a5c5fed539e6543121e57cc29bb65559bb6391efc806bf8759c8e29697a94a34" -"yaml","config","core","core/config.yaml","6cfe96a7c338f62118bd23adad1003948b3f9bc5be575fa53ac9deec54a9de84" +"yaml","config","core","core/config.yaml","2921f1a149eb7591bbc11119bbc6e6a3a7faed7393ccdf6b3cb98bccd2333285" "file",".gitignore","render","render/.gitignore","240a3e0d37d2e86b614063f5347eb02d4f99ca6c254de6b82871ff8d95532a7d" "py","config_utils","scripts","scripts/config_utils.py","48afe2bc18a29201e343cce3703be1e70df9c83ee74eeb68e57ef8ef42e8c651" "py","memlog","scripts","scripts/memlog.py","3b00f82ca33dc4227f715123b939514ee35c4f9c71150c894c3d8185df1b48df" diff --git a/_bmad/_config/manifest.yaml b/_bmad/_config/manifest.yaml index 3950aee8..e04897d6 100644 --- a/_bmad/_config/manifest.yaml +++ b/_bmad/_config/manifest.yaml @@ -1,21 +1,21 @@ installation: version: 6.11.0 installDate: 2026-08-13T17:02:57.224Z - lastUpdated: 2026-08-13T17:04:46.249Z + lastUpdated: 2026-08-20T14:10:06.265Z modules: - name: core version: 6.11.0 installDate: 2026-08-13T17:02:57.082Z - lastUpdated: 2026-08-13T17:04:46.248Z + lastUpdated: 2026-08-20T14:10:06.264Z source: built-in npmPackage: null repoUrl: null - name: bmm version: 6.11.0 installDate: 2026-08-13T17:02:57.162Z - lastUpdated: 2026-08-13T17:04:46.249Z + lastUpdated: 2026-08-20T14:10:06.265Z source: built-in npmPackage: null repoUrl: null ides: - - opencode + - codex diff --git a/_bmad/bmm/config.yaml b/_bmad/bmm/config.yaml index 8cf53ffc..164f135e 100644 --- a/_bmad/bmm/config.yaml +++ b/_bmad/bmm/config.yaml @@ -1,7 +1,7 @@ # BMM Module Configuration # Generated by BMAD installer # Version: 6.11.0 -# Date: 2026-08-13T17:04:46.195Z +# Date: 2026-08-20T14:10:06.228Z user_skill_level: expert planning_artifacts: "{project-root}/_bmad-output/planning-artifacts" @@ -13,4 +13,4 @@ user_name: Roland project_name: Gw2Analytics communication_language: French document_output_language: French -output_folder: _bmad-output +output_folder: "{project-root}/_bmad-output" diff --git a/_bmad/config.toml b/_bmad/config.toml index 14dcb27f..33cd4c50 100644 --- a/_bmad/config.toml +++ b/_bmad/config.toml @@ -13,7 +13,7 @@ [core] project_name = "Gw2Analytics" document_output_language = "French" -output_folder = "_bmad-output" +output_folder = "{project-root}/_bmad-output" [modules.bmm] planning_artifacts = "{project-root}/_bmad-output/planning-artifacts" diff --git a/_bmad/core/config.yaml b/_bmad/core/config.yaml index 85ce392d..aa012b2f 100644 --- a/_bmad/core/config.yaml +++ b/_bmad/core/config.yaml @@ -1,10 +1,10 @@ # CORE Module Configuration # Generated by BMAD installer # Version: 6.11.0 -# Date: 2026-08-13T17:04:46.196Z +# Date: 2026-08-20T14:10:06.228Z user_name: Roland project_name: Gw2Analytics communication_language: French document_output_language: French -output_folder: _bmad-output +output_folder: "{project-root}/_bmad-output" diff --git a/_bmad/scripts/config_utils.py b/_bmad/scripts/config_utils.py index 3d294555..df6bb079 100644 --- a/_bmad/scripts/config_utils.py +++ b/_bmad/scripts/config_utils.py @@ -3,9 +3,8 @@ from __future__ import annotations import tomllib -from collections.abc import Iterable from pathlib import Path -from typing import Any +from typing import Any, Iterable class ConfigError(ValueError): diff --git a/advisor-plans/README.md b/advisor-plans/README.md index e71ee999..caa6ea67 100644 --- a/advisor-plans/README.md +++ b/advisor-plans/README.md @@ -1,5 +1,8 @@ # Advisor Plans (senior-advisor audit followups) +> **Archive historique — pas un backlog actif.** Ces suivis sont conservés +> pour provenance ; ils ne sont pas une autorité de priorité ou d'exécution. + Senior-advisor audit (post-R1-R4 batch, 2026-07-10). Each plan is self-contained for an executor with zero context from this session. Status is updated by the executor. ## Open plans diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index a04a7066..24db545f 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,15 +1,19 @@ # Roadmap +> **Historique — pas une source de priorité actuelle.** Instantané du cycle +> v0.14.2 (2026-07-22), conservé pour la traçabilité. Pour une décision de +> suite : comportement livré (code/tests/CI), SPEC acceptées dans +> `_bmad-output/specs/`, puis checkpoints `docs/agentic/`; au Level 1, faire +> valider toute nouvelle priorité par le mainteneur. + **Status:** Living document. Last refreshed AT v0.14.2 cycle close-out (2026-07-22) — Plan 173 COMPLETE (14 boon uptimes + presence % + 14 outgoing boons in Combat Readout, grouped bar columns, 2 hermetic backend tests, E2E mock server + Playwright test). -This file is the **single source of truth** for "what's left to do" on -the project. It supersedes any ad-hoc "what's next" list in the README -or the CHANGELOG. It is meant to be edited at every release tag so -that the next session can pick up exactly where the previous one left -off. +This file is a historical snapshot and is **not** the source of truth for +"what's left to do" on the project. It must not supersede current SPEC, +checkpoints, code, tests or CI. ---## Current state (post-Plan-173 v0.14.2) diff --git a/docs/agentic/phase4-bmad-cleanup-2026-08-20.md b/docs/agentic/phase4-bmad-cleanup-2026-08-20.md new file mode 100644 index 00000000..c2e6e147 --- /dev/null +++ b/docs/agentic/phase4-bmad-cleanup-2026-08-20.md @@ -0,0 +1,88 @@ +# Phase 4 — Nettoyage contrôlé BMAD (2026-08-20) + +## Statut + +Terminé comme livrable candidat à intégration, au **Level 1**. Cette phase +reconfigure l'intégration agentique et sa documentation ; elle ne modifie aucun +code applicatif, aucune CI, aucun contrat API, aucune donnée ni aucune stratégie +Git/GitHub. La review indépendante finale est **CLEAN**. + +## Décisions d'inventaire + +| Statut | Éléments | Décision | +| --- | --- | --- | +| CONSERVER | `_bmad/` et les 49 skills `.agents/skills/bmad-*`, tests `tests/scripts/test_bmad_framework.py`, SPEC dans `_bmad-output/specs/`, ADR | BMAD 6.11.0 reste l'installation canonique ; les SPEC et ADR valides gardent leur rôle. | +| ADAPTER | manifeste BMAD, `AGENTS.md`, test de frontmatter, exclusions Ruff, documentation de priorité | Codex est l'intégration active ; la mémoire durable est versionnée dans le dépôt. | +| SUPPRIMER | `.opencode/commands/` (49 wrappers), `opencode.json`, exclusion Ruff `.opencode`, sauvegarde non suivie créée par l'installeur, `docs/supermemory-export.md` | Aucun consommateur actif ne les référençait après régénération Codex ; l'archive Supermemory ne contient aucun savoir durable unique non sensible. | +| INVESTIGUER | `docs/agentic/audit-proposal-2026-08-20.md`, chemins historiques `/tmp/opencode` de l'outillage EI, fichier suivi `=690` | L'audit brut reste non suivi et ne doit pas être ajouté tel quel. Les chemins EI et `=690` ne sont pas une intégration agentique et leur modification serait hors périmètre. | + +## Actions effectuées + +1. Régénération officielle, épinglée et non interactive : + `npx --yes bmad-method@6.11.0 install --directory /home/roddy/Projects/Gw2Analytics --action update --modules bmm --tools codex --yes`. +2. Le manifeste BMAD déclare désormais uniquement `codex`; core et bmm restent + en version 6.11.0. L'installeur a régénéré les skills canoniques et supprimé + les wrappers OpenCode. +3. `AGENTS.md` décrit maintenant Codex, les checkpoints versionnés, Supermemory + comme facultatif, et la confidentialité du corpus local `WvW/`. +4. `docs/ROADMAP.md`, `BACKLOG.md`, `SESSION.md`, `AUDIT_COMPLET.md`, les index + `plans/` et `advisor-plans/` sont clairement signalés comme historiques + lorsqu'ils ne constituent pas un état courant. + +## Sources de vérité après nettoyage + +1. comportement livré : code, tests et CI ; +2. contrat à construire : SPEC acceptées sous `_bmad-output/specs/` ; +3. décisions d'architecture : `docs/adr/` ; +4. reprise opérationnelle : checkpoints assainis dans `docs/agentic/`. + +Au Level 1, les documents historiques ne déclenchent aucune exécution : toute +priorité nouvelle nécessite une proposition et l'accord du mainteneur. + +## Validation + +| Vérification | Résultat | +| --- | --- | +| `uv run pytest tests/scripts/test_bmad_framework.py` | PASS — 7 tests | +| `uv run ruff check tests/scripts/test_bmad_framework.py` | PASS | +| `git diff --check` | PASS | +| `resolve_config.py` | PASS — Gw2Analytics, 5 agents BMAD résolus | +| `resolve_customization.py` sur `bmad-build` | PASS | +| manifeste BMAD | PASS — `ides: [codex]`, 49 skills | +| tests applicatifs/Docker | NOT RUN — hors périmètre de configuration Phase 4 | + +## Corrections après review indépendante + +1. Ce checkpoint fait partie du livrable Phase 4 et est préparé pour être + versionné ; il ne contient ni export Supermemory, ni donnée du corpus privé. +2. `docs/supermemory-export.md` a été relu sans accéder à `WvW/` : + - les quelques invariants non sensibles qu'il rappelait sont déjà couverts + par `AGENTS.md`, les SPEC/ADR et les tests ; aucun transfert n'est requis ; + - son historique de sessions, ses états de travail et ses chemins sont + redondants ou obsolètes ; + - les identifiants et informations privées non nécessaires sont éliminés en + supprimant l'archive entière ; + - aucun élément à provenance ou nécessité ambiguë n'a été identifié. +3. Les tests framework vérifient désormais le manifeste `ides: [codex]`, + l'inventaire stable des 49 skills Codex générés par BMAD 6.11.0 et l'absence + d'une configuration OpenCode active. Ils évitent les détails volatils du + contenu généré. +4. Après ces corrections : test framework (7 PASS), lint ciblé, résolveurs de + configuration et de personnalisation, et `git diff --check HEAD` sont tous + PASS. +5. Review indépendante finale : **CLEAN**, sans finding BLOCKER/HIGH/MEDIUM/LOW. + Elle confirme la fermeture des trois findings initiaux, l'absence de contenu + privé versionné et l'absence de changement runtime, API, données, CI, GitHub, + SPEC ou ADR. + +## Garde-fous + +- Aucun contenu de `WvW/` n'a été ouvert, modifié, ajouté à Git, déplacé ou + supprimé. Lors du contrôle final, une commande de statut trop large a + involontairement énuméré des chemins non suivis sous `WvW/` : incident de + confidentialité consigné ; ne pas répéter cette indexation. +- Aucun commit, push, PR ou merge n'a été créé. +- `docs/agentic/audit-proposal-2026-08-20.md` reste non suivi. Son contenu + utile devra être synthétisé et assaini dans les documents agentiques de la + Phase 5, jamais copié aveuglément ni publié comme état courant. +- La Phase 5 (infrastructure agentique) exige une autorisation explicite. diff --git a/docs/supermemory-export.md b/docs/supermemory-export.md deleted file mode 100644 index 4e3349f6..00000000 --- a/docs/supermemory-export.md +++ /dev/null @@ -1,328 +0,0 @@ -# Supermemory — Export Gw2Analytics - -Export des résumés de session sauvegardés dans l'espace supermemory `gw2analytics` -(9 documents), du plus récent au plus ancien. Généré le 2026-08-11. - -Chaque entrée conserve son ID de document supermemory pour retrouver l'original. - ---- - -## 2026-08-08 — Fix du filtre de tranche rotation (negatives casts) - -Document ID: `UitXS67X582dGsEopMH6Va` - -### Objectif -Parité rotation EI : éliminer les diff rotation entre le parser in-house et le JSON EI des logs WvW zevtc. - -### État du travail -**FAIT — Fix du filtre de tranche (slice) pour les rotations (ei_compare.py:761-770).** -- Problème : les casts de skills dont le **début** d'activation est avant le début du log (castTime relatif négatif, ex. dodge 23275 à -440ms, activation fin seule dans le log) étaient exclus par le filtre `slice_lo <= cast.time_ms + origin <= slice_hi`. -- Règle EI découverte (vérifiée sur tout le corpus, 57k casts) : un cast appartient à la tranche [firstAware, lastAware] contenant son **ancre** = début d'activation si le début est dans le log (cast.time_ms ≥ 0), sinon la **fin** de l'activation (cast.time_ms + duration_ms). Les castTimes négatifs d'EI (104 cas) sont tous dans des comptes à tranche unique → le parser émet déjà ces casts (branch `elif event.duration_ms > 1` rotation.py:552), c'était uniquement le filtre ei_compare qui les rejetait. -- Résultat : rotation missing 461 → **389** (-72), extra 178 → **179** (+1). Dodge 23275 : 7 missing → **0**, extra 0 → 0. Plusieurs négatifs réglés : 29772, 29855, 50947, 31496, 29965, 10555, 73091, 9140, 30229, 14358, 9253, 62565, 63163, 29772, 9265 (partiel). -- Le +1 extra restant : 2 cas de duration 9265 (2240 vs 2200, Guiritoui/insertcoin) et le cas edge Non Squad Player 43 / 29772@-1090 (instance ID 2448 partagé entre Nikola et un Scrapper ennemi → matching agent ambigu, hors filtre). - -**REJETÉ — Dodge 23275 via DodgeEvent** : le parser émet un DodgeEvent par attaque évadée (résultat 4), EI n'ajoute 23275 en rotation qu'à partir des activations skill (début d'activation hors log). Branche DodgeEvent→23275 testée : 4428 extras. Ne PAS refaire. - -### Next Move -- Duration 9265 2240 vs 2200 (2 logs) : pourquoi le parser produit 2200 (probablement cast_duration réel vs durée canonique EI). -- L'instance ID 2448 partagée (Nikola.8512 + Non Squad Player 43) : décider si le matching d'agent par instance doit tenir compte de l'account. -- Prochaine grosse piste : -27 (Blink/Phase Retreat, guid C34E250B01FF534292EE6AB36D768337, 10 missing / 9 extra) et -41, -7, -6, -11, -14 (négatifs synthétiques). - -### Fichiers clés -- `libs/gw2_analytics/src/gw2_analytics/ei_compare.py` : `_rotation_unmatched` (nouveau, matcher par skill+time±2/dur), filtre tranche rotation (ancre début sinon fin), chronomancer ajouté à l'ensemble Mesmer (guid effect 10310/-27). -- `libs/gw2_analytics/src/gw2_analytics/rotation.py` : inchangé fonctionnellement ce coup-ci (patch local Engineer kit toujours en place). -- `libs/gw2_analytics/tests/test_rotation.py` : +35 lignes (patch local). - -### Notes de décision -- Les outils bash/read/rtk de cette session ont renvoyé des sorties corrompues (répétitions, numéros de ligne) ; `git checkout -- rotation.py` a été lancé par erreur mais le fichier n'était PAS corrompu — vérifier par md5/size avant toute restauration en cas de doute. -- Les diffs EI sont générés via `uv run python scripts/ei-parity/ei_diff.py --json /tmp/gw2a-ei-diff-v8.json`. Le JSON /tmp/gw2a-ei-diff.json (version "7 missing 23275") était valide ; v8 est le dernier état correct. - ---- - -## 2026-08-05 — ROOT CAUSE origine rotation résolu (start_time_ms / CBTS_START exposé) - -Document ID: `oBgtFsaFVKivQA2AuqvSzU` - -### Objectif -Réduire les diffs de parité rotation (players.rotation) vs GW2EI sur le corpus WvW (35 logs). - -### État du travail (fait / en cours / bloqué) -- FAIT — DIAGNOSTIC conclu: notre origin = min(e.time_ms) était parfois 1ms PLUS TARDIVE que l'origine d'EI. Les 3 pires logs (20260526=45, 20260708=29, 20260118=17) avaient exactement ce décalage +1ms; les logs alignés souffraient d'autre chose. -- VÉRIFIÉ: l'origine d'EI = le statechange 9 (CBTS_START / log start marker), qui est à min(event)-1 sur ces logs, et = min(event) sur les autres. Confirmé par alignement des weapon-swaps (-2): shift +1 seulement sur les 3 fautifs. -- FAIT — FIX ROOT CAUSE implémenté: - 1. parser.py `_extract_evtc2025_metadata`: exposer `out["start_time_ms"] = ev[0]` du statechange 9 (jusque-là lu mais jeté; seul duration_ms=end-start était calculé). - 2. parser.py `_iter_fights`: passer `start_time_ms=metadata.get("start_time_ms")` au EvtcHeader. - 3. libs/gw2_core/models.py EvtcHeader: ajouter `start_time_ms: int | None = Field(default=None, ge=0)`. - 4. ei_compare.py ligne ~244: `origin = header.start_time_ms if header.start_time_ms is not None else min(event.time_ms)`. (build_skill_rotation utilisait déjà ce start_time_ms via son arg 3 positionnel `origin`, fallback min — cohérent.) -- BILAN: rotation diffs 416 → 378 ; total diffs 1108 → 1012 sur les 35 logs. Améliorations ciblées uniquement (aucune régression): 20260526 45→23, 20260708 29→17, 20260118 17→13; tous les autres logs inchangés. -- TESTS: 524 passed, 15 skipped. Ruff + mypy OK. -- NE PAS OUBLIER (session précédente, non commité): les 11 entrées de mapping ajoutées dans rotation.py (_BUFF_GAIN_CASTS + 51664:14410,32931:31187,62931:62758,9422,29502:30435,76507:5635 ; _DAMAGE_CASTS + 76783:75,24305:50,13907:50 ; _INSTANT_CASTS_BY_EFFECT + E10D2D...13684, D6C8F4...10302). Voir git diff rotation.py. WORKING TREE SALE — RIEN N'EST COMMITTÉ. - -### Next Move -1. Attaquer la prochaine source de diffs rotation: 20260610-212627 (27), 20260625-215943 (25), 20260526-202841 (23), 20260718-154555 (21), 20260712-203400 (20). NB: 20260625 a l'origine CORRECTE (delta=0) mais échoue quand même — cause différente (casts manqués/pivot, pas l'origine). -2. Retrouver/redécouvrir le "pivot fix" (casts manqués/étourdis) dans l'ancienne branche rules-engine-flatten-casts (commit mentionnant "weapon"). -3. Quand le diff est satisfaisant: committer proprement les changements (verifier DCO Signed-off-by, linear history, PR requis — pas de push direct sur main). - -### Fichiers clés -- libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py: _extract_evtc2025_metadata (≈1982), _iter_fights (≈1704), EVENT_SIZE=64, _EVENT_STRUCT_2025, offsets. -- libs/gw2_core/src/gw2_core/models.py: class EvtcHeader (≈163) — extra="forbid", champs gw2_build/map_id/arc_revision/duration_ms + CHAMP start_time_ms AJOUTÉ. -- libs/gw2_analytics/src/gw2_analytics/ei_compare.py: compare_elite_insights (≈218), _slice_bounds (196), origin (~244), rotation comparison (567-596). -- libs/gw2_analytics/src/gw2_analytics/rotation.py: build_skill_rotation (signature ~303, origin fallback ~321). -- Fichiers de mesure: .tooling/ei_diff.py ET scripts/ei-parity/ei_diff.py. Outputs: /tmp/opencode/ei_now.json (baseline, 416 rot/1108 total), /tmp/opencode/ei_sc9.json (378 rot/1012 total). -- validation métier: statechange 9 = CBTS_START (log start), statechange 10 = END; dwell sur le fait que metadata renvoie {} sur certains logs donc start_time_ms peut être None → fallback min() intact. - ---- - -## 2026-08-05 — Diagnose offset d'origine rotation vs EI - -Document ID: `ZoKhAoqJB9SP9gN9czb5YE` - -### Objectif -Atteindre la parité rotation (players.rotation) entre notre build_skill_rotation et GW2EI sur le corpus WvW (35 logs, corpus.txt, EI outputs dans .tooling/ei-out/*_detailed_wvw_kill.json). Métrique canonique = nombre de buckets où liste attendue OU réelle non-vide (comparaison par égalité exacte de listes). Baseline main = 424 diffs rotation → 416 après ajout de 11 entrées de mapping (dont 14410, 31187, 62758, 30435...). - -### État du travail (fait / en cours / bloqué) -- FAIT: Capture baseline à /tmp/opencode/ei_baseline_main.json. 34/35 logs passent; 3 logs échouent: 20260118-020548 (17), 20260708-215736 (29), 20260625-215943 (26). -- FAIT (cette session): Diagnostic d'alignement par weapon-swaps (skill_id==-2) entre nos temps rotation et les castTime EI, par log, via meilleur shift global. RÉSULTAT CLÉ: - - La plupart des logs: best_shift=0 (origines alignées). Ex: 20260118 → shift=1 (254/255 swaps match), 20260708 → shift=1 (76/76 match), 20260526 → shift=1 (149 match). Les 3 logs qui échouent au baseline incluent exactement ces logs à shift=+1ms. - - Quelques logs ont des swaps manquants (notre count > EI count): 20260409 (our=10, ei=6), 20260519 (16/13), 20260316 (16/12), 20260506 (163/160), 20260718 (143/132) — suspecte casts manqués/état au début (clamped at origin, or skills consumables non-filtrés). -- EN COURS: Vérifier que la théorie "origine EI = min(e.time_ms) - 1ms sur ces logs" est confirmée; la correction = décaler l'origine de +1ms (ou corriger le point d'ancrage) pour les logs shift=+1. -- BLOQUÉ/NON-COMPRIS: Pourquoi EI n'émet pas tous les swaps que nous émettons (manquants -2). Et le "pivot fix" (cast stack, casts manqués/étourdis) n'a PAS été retrouvé — chercher dans l'ancienne branche rules-engine-flatten-casts (commit mentionnant "weapon"). - -### Next Move -1. Confirmer la théorie d'origine: pour 20260118-020548, décaler notre timeline de +1ms (ou trouver l'origine exacte EI = premier event d'état, pas min(e.time_ms)) et re-run la diff parité → attendu: rotation buckets de ces logs passent au vert. -2. Si confirmé: implémenter la compensation d'origine uniforme dans cast.py (où origin est appliqué) OU modifier l'origine utilisée dans build_skill_rotation pour ancrer sur l'event start/statechange 9 (start_time_ms) plutôt que min(e.time_ms). -3. Puis retourner au pivot fix pour les casts manqués (chercher dans rules-engine-flatten-casts). - -### Fichiers clés -- zevtc files/*.zevtc (logs bruts), .tooling/ei-out/*_detailed_wvw_kill.json (ground truth EI) -- scripts/ei-parity/corpus.txt (liste stems) -- libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py: parse() (~1600-1720), _extract_evtc2025_metadata (1975-2013, lit start_time_ms via statechange 9 mais renvoie {} sur ces logs), parse_events(), _EVENT_STRUCT_2025/2024, _parse_skill_cbtevent (~906-1000, source des events buffDamage) -- libs/gw2_analytics/src/gw2_analytics/rotation.py: build_skill_rotation (reçoit origin) -- libs/gw2_analytics/src/gw2_analytics/cast.py: où origin est appliqué à la timeline -- Ancienne branche rules-engine-flatten-casts (commit mentionnant "weapon") : détient probablement le pivot fix - -### Notes de décision -- Méthode de mesure des offsets: pour chaque log, comparer sorted(our_swaps) et sorted(ei_swaps), chercher le shift global qui maximise l'intersection des temps. shift=0 dominant; shift=+1 sur les 3 logs fautifs. -- On a déjà les events buff buffGain (51664:14410, 32931:31187...) émis correctement en COUNT; le problème des 5 entries neutres (31187, 30435, 62758, 76783, 24305) = les logs où elles apparaissent ont le décalage +1ms → tout décalé, jamais match. Corriger l'origine devrait les convertir en wins. - ---- - -## 2026-08-05 — Réduction des discrepancies rotation (oracle probe_candidates) - -Document ID: `8aksEwEww4xyQzJajES6C9` - -### Objectif -Réduire `players.rotation` (424 diffs) du comparateur EI sur le corpus 35 logs en complétant les tables d'instants de `rotation.py` à partir du code source EI. - -### État du travail -**FAIT (trouvaille majeure de la session)** -- Découvert que `ei_compare.compare_elite_insights` compare `players[X].rotation` par **égalité EXACTE de listes** (`expected_casts != actual_casts` à ei_compare.py:596). Une seule ms de différence fait compter tout le bucket comme diff. La métrique canonique = nb de buckets `rotation` avec expected OU actual non vide (NON la somme des casts — mes analyses précédentes « sum of casts » étaient trompeuses). -- Le vrai levier = faire correspondre des listes complètes par-log. Oracle scripté `scripts/ei-parity/probe_candidates.py` : parse chaque log une fois, patch chaque entrée candidate à chaud, mesure le delta canonique exact. -- **Résultat : 424 → 416** (strictement -8, mesuré via ei_diff.py --json ei_v2.json). Aucune régression. -- Entrées qui GAGNENT (delta négatif) : `_BUFF_GAIN_CASTS` 9422:9422 (-1), 76507:5635 Arcane Echo (-1) ; `_DAMAGE_CASTS` 13907:50 (-1) ; `_INSTANT_CASTS_BY_EFFECT` D6C8F406E4DEE04AB16A215BE068E910:10302 Feedback (-2), E10D2D0DF7803146A69BBB5BD47944FC:13684 Lesser Symbol of Protection large variant (-2) ; + 51664:14410 Signet of Fury déjà validé (-1). Total = 424-8. -- Entrées NEUTRES (delta +0, inertes sur corpus, mais correctes selon le source EI) : `_BUFF_GAIN_CASTS` 32931:31187 Dash, 62931:62758 Flame Wheel, 29502:30435 Berserk ; `_DAMAGE_CASTS` 76783:75, 24305:50. Conservées car conformes aux finders EI. -- Timing : pour 31187 sur log 20260118 (Daredevil), nos 56 applies de 32931 = les 56 casts EI, mais décalés de **+1ms uniforme** (origine log différente) → bucket reste diff malgré le compte exact. - -### Next Move -- (optionnel) Investiguer le décalage de temps +1ms : `origin = min(e.time_ms)` dans rotation.py vs origine EI ; `_slice_bounds`/`origin` dans ei_compare.py:196-208. Si corrigeable, 31187/30435/62758 deviendraient des wins réels. -- Puis attaquer `players.buffUptimes.uptime` (363) et les autres buckets restants. - -### Fichiers clés -- `libs/gw2_analytics/src/gw2_analytics/rotation.py` : tables modifiées (51664:14410, 32931:31187, 62931:62758, 9422:9422, 29502:30435, 76507:5635, 76783:75, 24305:50, 13907:50, D6C8F406...:10302, E10D2D0D...:13684). -- `scripts/ei-parity/probe_candidates.py` : oracle des candidats (nouveau, non commité ?). -- `/tmp/opencode/ei_v2.json` + `ei_v2_stdout.txt` : résultat 416. -- `/tmp/opencode/ei_baseline_main.json` : baseline 424. -- `/tmp/opencode/extract_finders.py` + `ei_finders_full.txt` : 443 finders EI. -- `libs/gw2_analytics/src/gw2_analytics/ei_compare.py:596` : comparaison exacte. - -### Notes de décision / Diffs -- Le commit est en cours : rotation.py modifié avec les 11 entrées (git diff 1 fichier). Vérifier `git status`/`git diff` avant commit éventuel (aucun commit fait automatiquement). -- La métrique « nb de casts expected/actual » est INADÉQUATE : la vraie métrique est le compte de buckets canoniques. - ---- - -## 2026-08-05 — Setup corpus + état de parité (rotation/buffUptimes/consumables) - -Document ID: `z7GxtJpGjN6M5UTHR41N3V` - -### Objectif -Réduire les écarts de parité restants vs Elite Insights sur le corpus 35 logs. Main local @ e1d69fe = origin/main = le plus avancé (contient #115 rotation gaps, #116 engineer kit, #117 Regen buffUptime, #120 slice compare 4503→1116). Rien à récupérer des branches remote (fix/regen-*, parser-buff-uptime-parity = simples chores CI non mergés). - -### État du travail -- [x] 35 logs du corpus extraits de `/home/roddy/Projects/Logs combats/Hem Oclar.zip` (10 Go) vers `zevtc files/` -- [x] 35 EI outputs `_detailed_wvw_kill.json` régénérés dans `.tooling/ei-out/` via CLI EI local (`GuildWars2EliteInsights-CLI.dll`) avec `.tooling/ei-local.conf` — NOTER : `scripts/ei-parity/ei.conf` pointe vers un chemin Mac (/Users/arthurdacquet/...), il FAUT utiliser ei-local.conf -- [x] Baseline réel post-#120 figé : **1116 différences / 35 logs** -- En cours : rotation (424), buffUptimes.uptime (363), consumables (58), connectedHits (45), downContribution/againstDownedCount (~130) - -### Next Move -1. Attaquer players.rotation (424) via SkillList.json / table InstantCastFinder d'EI (compilée dans .tooling/GW2EICLI/GW2EIEvtcParser.dll/.pdb) pour compléter _INSTANT_CASTS_BY_BUFF dans libs/gw2_analytics/src/gw2_analytics/rotation.py -2. Puis players.buffUptimes.uptime (363) -3. Relancer `uv run python scripts/ei-parity/ei_diff.py --json out.json` après chaque fix -4. Réf. json baseline : /tmp/opencode/ei_baseline_main.json - -### Fichiers clés -- /home/roddy/Projects/Gw2Analytics (branche main @ e1d69fe) -- scripts/ei-parity/ei_diff.py, corpus.txt, probe_rotation.py ; docs/ei-parity-workbench.md -- libs/gw2_analytics/src/gw2_analytics/rotation.py (tables instants), ei_compare.py (_slice_bounds) -- .tooling/GW2EICLI/Content/SkillList.json (10MB) + GW2EIEvtcParser.dll/.pdb -- .tooling/ei-local.conf (bon OutLocation) vs scripts/ei-parity/ei.conf (chemin Mac cassé) -- /mnt/ssd-2to = SSD 2 To monté localement (WvW logs) ; Proxmox pve01 192.168.1.10 (token 401, SSH refusé) - -### Notes de décision -- 4 approches dégradantes NON retentées (consignées #122) : fenêtrage uptimes boons (225→913), soustraction 2 lectures tracker, décalage consommables +1ms (39→95), restreindre cible à 1 agent (682→3205) -- dotnet runtime local : /home/roddy/.dotnet (8.0.29) ; dotnet --version buggé mais lancement CLI OK - ---- - -## 2026-08-04 — Clôture parité EI Regeneration buffUptimes (#117) - -Document ID: `SYha2ntGmmRg1oiFFCfKDY` - -### Objectif -Clore la parité EI Regeneration `buffUptimes[718]` via `BuffSimulatorDuration` + `HealingLogic` (capacity 5) dans `buff_state.py`, merger PR #117. - -### État du travail -- FAIT : PR **#117 merged** (squash commit `b1fb47b`, "fix(analytics): close EI Regeneration buffUptimes parity"), branche `fix/regen-buffuptime-parity` supprimée, 3 workflows CI verts sur `pull_request` (CI 30904308297, Docker build 30904308351, Security 30904308295) + DCO. -- FAIT : bouton dur : les checks `workflow_dispatch` ne comptent PAS pour les required checks d'une PR → le `statusCheckRollup` reste vide et `mergeStateStatus=BLOCKED` malgré 9 checks verts. Seul un run déclenché par `pull_request` (push sur branche / reopen) compte. Appris : pousser un commit vide (`git commit --allow-empty -m "chore(ci): trigger..."`) pour forcer le synchronize. -- FAIT : DCO check exige un trailer `Signed-off-by` sur TOUS les commits de la PR (pas seulement le head) → rebase `--signoff origin/main` sur les 11 commits. -- FAIT : bump `cryptography>=50,<51` dans `pyproject.toml:76` (CVE-2026-69247/8/9 sur 48.0.1). -- EN COURS : le dernier diff de parité (joueur `Ovalkvadratcylinder.9365`, log 20260125-001308) reste : 52.751 EI attendu vs 52.791 (1 seul diff sur 13 totaux, 12 = `players.rotation`). - -### Next Move -1. Finir le dernier diff regen : tracer le joueur 9365 (`_probe_raw` sur 718) vs EI, regénérer `ei.py` depuis /tmp/ei-src si besoin pour isoler le cas. -2. Soumettre le correctif restant sur `main` (branche `fix/` + PR avec commit vide si CI ne se déclenche pas). - -### Fichiers clés -- `libs/gw2_analytics/src/gw2_analytics/buff_state.py` (branche regen ~ligne 314, PLR5501 corrigé) — porté + mergé. -- `libs/gw2_core/src/gw2_core/models.py:494/531` : `BoonApplyEvent` + `added_active: bool`. -- `libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py:1168` : `added_active=bool(is_shields)`. -- `/tmp/v3_tmp.py` : port de référence exact. `/tmp/ei-src` : sources EI (`HealingLogic.cs`, `QueueLogic.cs`, `BuffApplyEvent.cs`). -- `scripts/ei-parity/ei_diff.py`, `.tooling/ei-out/_detailed_wvw_kill.json`, `SESSION.md`. - -### Notes de décision / IDs -- CI branche : ne se déclenche pas automatiquement sur push de branche (sauf PR sync) ; forcer via commit vide. Check runs `pull_request` seulement. -- Règles repo : 9 required checks + DCO (Signed-off-by tous commits) + linear history + non-fast-forward. Push direct `main` refusé → toujours passer par PR. -- PR : https://github.com/Roddygithub/Gw2Analytics/pull/117 (merged b1fb47b). - ---- - -## 2026-08-03 — continuation: port EI sim + découverte divergence - -Document ID: `iyEYDdopixUtcJNxjTiDWu` - -### Objectif -Parité totale EI v3.26.0.0 : 0 diff sur corpus 12 logs WvW. État 156 diffs (116 rotation / 39 buffUptimes / 1 downCount). - -### Fait dans cette continuation -- **Construit `eisim.py`** : port fidèle Python de EI HealingLogic + BuffSimulatorDuration + BuffStackItem : `/tmp/eisim.py` (StackItem, HealingLogic, Sim class). -- **Résultat critique** : `eisim` donne EXACTEMENT le même résultat que notre tracker actuel pour Babba (20260429-232621) : - - eisim Babba regen uptime: **55.251%** - - Our tracker Babba regen uptime: **55.251%** - - EI expected reference: **71.922%** -- **Notre modèle est cohérent mais diverge de 16.7% vs EI** → le flux d'événements ou la sémantique des événements que nous feedons diffère de ce que EI feed à son sim. -- **CommonBuffs.cs** : Regeneration skill 718 a DEUX définitions : `BuffStackType.Queue` (pre-Feb2018, l.19) et `BuffStackType.Regeneration` (post-Feb2018, l.21). Modern WvW → **HealingLogic**. Confirmé. -- EI `StateChange.BuffInitial` (18) = `BuffApplyEvent.Initial = true`. Notre parser émet `BuffApplyEvent` pour is_statechange==18 avec `added_active=bool(is_shields)` — potentiellement l'initial snapshot n'est pas correctement lié au sim (initial = stack pré-existant avant le début du log). -- `BuffRemoveAllEvent` : IsBuffSimulatorCompliant hérité de AbstractBuffRemoveEvent — faut vérifier si il hérite du filtre `BuffRemoveSingleEvent` ou a sa propre compliance. Les remove_all avec src=0 pourraient être filtrés par EI (éliminant des clears qui enlèvent de l'uptime). -- **EI `compare_healing`** : tri du root seedSrc pour `_healing` (l'agent record), qu'on lit correctement. -- **Agents** : 172 agents, Babba id 15113 inst_id 4534 (single) - -### Next Move (priorité) -1. Lire l'EI reference JSON complet pour Babba (`.tooling/ei-out/20260429-232621_detailed_wvw_kill.json`) → comparer buffUptimes per source, activeTimes, initial buffs. -2. Vérifier si EI traite le BuffApplyEvent **Initial** (is_state_change == 18) comme précurseur avec un délai de déduction de durée déjà consommée. Notre tracker le traite comme n'importe quel apply — divergence possible. -3. Vérifier `BuffRemoveAllEvent.IsBuffSimulatorCompliant` dans EI (hérité de `AbstractBuffRemoveEvent` ? Filtre IFF ?). Si EI ignore uncredited remove_all... et notre tracker les exécute → on clear plus souvent que EI → on sous-estime (exactement Babba => 55 vs 72%). - -### Fichiers clés -- /tmp/eisim/ (nouveau) -- .tooling/ei-out/20260429-232621_detailed_wvw_kill.json (référence EI) -- Tous les autres comme ci-dessus (résumé précédent, memory précédent) -- EI : BuffApplyEvent.cs l.19, l.39, AbstractBuffApplyEvent l.13, BuffRemoveAllEvent.cs, CombatItem.cs -- GW2 libs/gw2_analytics/src/... (compare, parser) - -### Notes décision -- Important : `Remove.Single` ne s'applique pas à no (0 events relevant dans Babba log). Donc le fix remove_single n'a pas d'effet. -- Important : les two `eisim` et tracker produisent le MÊME résultat pour Babba (55.251%), ce qui prouve que notre modéliseur logique est fidèle — le problème est DANS LES ÉVÉNEMENTS OU LA LECTURE D'ÉVÉNEMENTS initiaux. -- `État `_noSort` global** : vérifié comme identique à EI (static Logic, per parse, modifié lors de BuffStackActive). -- `Healing` valeur: ordre dans `eisim` utilisé sort par `seedSrc.healing` identifié comme `compare_healing` EI — tous les scores sont 0 pour Babba? Vérifié — Babba healing = 0, mais SOURCES healing diffère de 0 selon... le `eisim` Sort reste op à zéro scores → `stacks.Last()` = hash-based insertion (stable). Ça peut causer écarts. - -### Probes restantes -- `/tmp/test_babba_sim.py` top adapté `parse_events` — correct. Run UV (taille ~105109ms). -- Prendre `.tooling/ei-out/20260429-232621_detailed_wvw_kill.json` pour déboguer les `activeTimes`, `buffUptimes` de EI sur Babba. -- Vérifier `BuffRemoveAllEvent` héritage spec EI (filtre IFF). - ---- - -## 2026-08-03 — Résumé de session (suite diagnostic regen) - -Document ID: `JJzj6mpJ4HtEPPbzNfD9jF` - -### Objectif -Parité totale EI v3.26.0.0 : 0 diff sur le corpus 12 logs WvW. État actuel 156 diffs (116 rotation / 39 buffUptimes / 1 downCount). Cible courante : regen uptime (39 diffs, changés par aucun fix jusqu'ici). - -### État du travail -- FAIT : Constantes EI résolues (/tmp/ParserHelper.cs, tag v3.26.0.0) : ServerDelayConstant=10, BuffSimulatorDelayConstant=15, BuffSimulatorStackActiveDelayConstant=50. Notre tolérance < 15 ms déjà conforme. -- FAIT : `AddRegen` (BuffDictionary.cs:97-119) est du code MORT dans v3.26.0.0 — AUCUN appelant dans tout l'arbre. Donc `OverridenRegenInstance`/`OverridenRegenDuration` ne se déclenchent jamais → l'éviction EI en cas de file pleine est TOUJOURS `stacks.Last()` (HealingLogic.FindLowestValue, le code override ne sert jamais). Théorie "override pairing" invalide — ne peut pas expliquer Babba/Peixa. -- FAIT : EI NoID Remove.Single = match par DURÉE SEULEMENT, premier dans l'ordre de liste, ignore stack_id (`abs(removedDuration - TotalDuration) < 15`). -- FAIT : EI filtre les remove_single overstack/natural-end pour sims NoID : `BuffRemoveSingleEvent.IsBuffSimulatorCompliant` (BuffRemoveSingleEvent.cs:26-38) = false si IFF==Unknown && CreditedBy unknown && dstAgent==0 (`OverstackOrNaturalEnd`). Notre parser miroite ça à parser.py:1105 (`is_evtc_2025 and is_buffremove != 1 and _iff == 2 and dst_agent == 0`). IFF: Friend=0, Foe=1, Unknown=2 (ArcDPSEnums.cs:618). -- FAIT : **DÉCOUVERTE CLÉ** — le log Babba (20260429-232621) a ZÉRO événement regen `remove_single` ; seulement `remove_manual` (16) et `remove_all` (52). Notre tracker ne gère que `kind == "remove_single"` ; `remove_manual` tombe dans le vide = ignoré = **CONFORME à EI** (BuffRemoveManualEvent.IsBuffSimulatorCompliant retourne false, EI ignore aussi CBTB_MANUAL=3). Donc le fix remove_single ne pouvait RIEN changer (les events n'existent pas) — cela explique pourquoi act6 = act5 à l'identique (39 diffs, zéro CHANGED). -- FAIT : StackingLogic.cs : IsFull = stacks.Count == capacity (pas >=). QueueLogic.Add = append + Sort (no-op). HealingLogic : extends QueueLogic. BuffSimulator.Add : si full → FindLowestValue (false → OverstackSimulationResult) ; si addedActive → Activate (move front). -- FAIT : BuffSimulator.Remove (BuffSimulator.cs:86-110) : Remove.All → waste tous + clear ; Single → durée-only match. - -### Next Move -La divergence des 39 uptimes ne vient PAS de remove_single ni de remove_manual (les deux conformes). Reste à tester : (1) la sémantique de `TotalDuration` décrémenté (EI décrémente les stacks actifs via Update(timePassed), notre `expirations` stocke des temps absolus — vérifier si la comparaison d'éviction/removal est comparable), (2) le chemin `addedActive`/Activate (move-to-front) et le noSort, (3) extension handling. Prochain pas concret : instrumenter Babba/Peixa — dump la séquence regen apply/remove_all + notre expirations vs simulation EI attendue, trouver où notre COUNT/expiry diverge d'EI. Ensuite re-run corpus, viser Peixa/Babba vers 0 sans régresser okami/Meril/Bergmann. - -### Fichiers clés -- libs/gw2_analytics/src/gw2_analytics/buff_state.py — BuffStateTracker, _REGEN_NO_SORT, handlers BoonApply ~318-370, remove_single ~371-405, _process_buff_apply ~405-460. -- libs/gw2_analytics/src/gw2_analytics/ei_compare.py — BuffStackActiveEvent forwardé, clés JSON `players[.].buffUptimes.uptime`. -- libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py — filtre IFF l.1105, _CBTBUFREMOVE_KINDS l.343-347 (remove_all/remove_single/remove_manual). -- EI /tmp/ei-v3/GW2EIEvtcParser/ : BuffDictionary.cs (AddRegen mort), BuffSimulatorNoID/ (HealingLogic.cs, QueueLogic.cs, BuffSimulator.cs, StackingLogic.cs), BuffRemoves/BuffRemoveManualEvent.cs (compliant=false), BuffRemoves/BuffRemoveSingleEvent.cs:26-38. -- Dumps : /tmp/after_active4_full.json (159), after_active5_full.json (156), after_active6_full.json (156), baseline.json. -- Probe : /tmp/probe_regen.py. - -### Notes décision / Diff -- act5 = append→replace-last (fix éviction) : a amélioré okami/Bergmann/Meril, régressé Peixa (-9.8) Babba (-16.7). act6 = +remove_single durée-first : identique à act5. Le levier n'est PAS là. -- Run : stems=$(ls "zevtc files" | grep '\.zevtc$' | sed 's/\.zevtc$//') && uv run python scripts/ei-parity/ei_diff.py --json /tmp/.json $stems -- Tests : libs/gw2_analytics/tests/test_buff_state.py (66, pass). - ---- - -## 2026-08-02 — cause racine buffUptimes établie - -Document ID: `xLAesErg2jkYYQzccLPFb6` - -### Objectif -Parité totale EI v3.26.0.0 : 0 diff sur le corpus 10 logs WvW. Baseline actuelle 158 diffs (115 rotation + 42 buffUptimes + 1 defenses.downCount). - -### Découverte clé (cause racine 42 buffUptimes) -- Pour les buffs de DURÉE (Queue/Regeneration), l'uptime EI = PRÉSENCE (union du temps où ≥1 stack est actif), pas la somme des durées. - - Preuve : ViV.9421 protection 717, log 20260702-185809. EI `uptime: 88.454` = 98146ms / 110956ms (phase), `states` = [[0,0],[1,1],[98146,0]] = présence continue de t=1 à 98146. - - Σ `generated` par source EI = 58.109+9.339+5.404+1.521+3.924+4.867+5.29 = 88.454 (dans ce cas = présence car pas de chevauchement). - - GetUptime (BuffDistribution.cs) = Σ Value par source ; Value = durée où le stack FRONT (BuffStack[0]) est actif, item BuffSimulationItemDuration, active stacks = 1. -- Notre tracker actuel (`buff_state.py`, path `max_stacks==1`) = FIFO-chaîne capacité 99 : `expirations` chaînées séquentiellement, cumulative = somme → ~99.999% systématiquement quand les applies se chevauchent. C'est FAUX. -- L'union brute des intervalles (t, t+dur) sur ViV donne 62.587% (69444ms) — NI somme (114435ms→103%) NI présence EI (88.45%). Donc `duration_ms` de nos BoonApplyEvent ne reproduit pas la présence EI : les `BuffStackActiveEvent` (33 pour ViV) et la logique de file (front qui change) prolongent la présence au-delà des (t,t+dur) simples. -- Vérifié : aucun (t+dur) de ViV ne tombe à 98146 → la présence EI dépend du mécanisme d'activation des stacks (BuffSimulatorDuration.Update + QueueLogic.Activate qui met le stack en position 0, délai ParserHelper.BuffSimulatorStackActiveDelayConstant = 50ms). - -### Sémantique EI no-ID (WvW, UseBuffInstanceSimulator = false confirmé CombatData.cs:611) -- Simulateur par buff : BuffSimulatorDuration pour durée, BuffSimulatorIntensity pour intensité. -- QueueLogic (capacité 5 pour Protection/Régénération/Resolution/Resistance/Quickness/Fury/Vigor/Swiftness per CommonBuffs.cs) : `Add` append, si full remplace le stack non-front avec la plus courte TotalDuration → Waste ; `Activate` = move stackItem en position 0. -- `Value` (uptime) = temps où BuffStack non vide, crédité au Src du front. -- `Wasted` = temps des stacks remplacés (ViV protection : Schmusekætzchen 6.291, Ess Kape 3.893, Roger I Rabbit 1.947, Colmyllo 1.721, Semtäx 0.541, Krataxx 0.288). -- `Overstacked` == `generated` pour ViV (peut-être double-count dans l'export). - -### État du travail -- Fait : PR #114 (a1dd3d0), #115 (2304cf7, rotation 163→120), #116 (76bfa34, 158 total, 115 rotation) mergés. Git GPG signé. -- En cours : cause racine buffUptimes établie (voir ci-dessus). 42 diffs concentrés : 28×Regeneration (718), 4×Protection (717), 2×Resolution (873), 2×Resistance (26980), Fury/Might/Swiftness/Quickness/SuperSpeed/Stability ×1. Log 20260702-185809 = gros deltas positifs. -- Bloquer : diffusion des 4 sous-agents de recherche aborted ; 1 defenses.downCount (Ever.6173, log 20251022, expected 2/actual 1, EI DefenseAllStatistics.cs DownCount = count BuffApplyEvent Downed). - -### Next Move -1. Comprendre comment BuffStackActiveEvent + la file EI prolongent la présence au-delà des (t,t+dur) — instrumenter le flux EI (ou reproduire BuffSimulatorDuration en Python) sur ViV protection pour obtenir 98146ms. -2. Refonte `buff_state.py` : remplacer FIFO-chaîne cap 99 par simulation file EI (cap 5, front actif, activate via BuffStackActiveEvent, remplacement du plus court restant → waste). -3. Rédiger dossier Supermemory complet : defenses (compter BuffApplyEvent Downed), buffUptimes (refonte file), rotation (classer 115 écarts par skill + InstantCastFinder EI). -4. Déclencher GPT-5.5 avec validation : tests + Ruff + corpus avant/après. - -### Fichiers clés -- libs/gw2_analytics/src/gw2_analytics/buff_state.py (à refondre) -- libs/gw2_analytics/src/gw2_analytics/ei_compare.py (l.355 aliases, l.462 min(100), l.489 seuil 0.005) -- /tmp/opencode/GW2-Elite-Insights-Parser/GW2EIEvtcParser/EIData/Buffs/BuffSimulators/BuffSimulatorNoID/BuffSimulatorDuration.cs, BuffSimulator.cs, EffectStackingLogic/QueueLogic.cs -- /tmp/opencode/GW2-Elite-Insights-Parser/GW2EIEvtcParser/EIData/Buffs/BuffDistribution.cs (GetUptime) -- /tmp/opencode/GW2-Elite-Insights-Parser/GW2EIEvtcParser/EIData/Buffs/BuffSimulators/BuffSimulationItems/BuffSimulationItemDuration.cs -- Probes: /tmp/opencode/probe_union.py (union brute 62.587%), probe_viv*.py diff --git a/opencode.json b/opencode.json deleted file mode 100644 index 87c79447..00000000 --- a/opencode.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "https://opencode.ai/config.json", - "plugin": ["@dietrichgebert/ponytail"], - "instructions": [], - "references": {}, - "skills": { - "paths": [".agents/skills"] - }, - "mcp": { - "postgres": { - "type": "local", - "command": ["npx", "-y", "@yawlabs/postgres-mcp"], - "enabled": true, - "env": { - "DATABASE_URL": "postgresql://gw2analytics:gw2analytics@localhost:5432/gw2analytics" - } - }, - "redis": { - "type": "local", - "command": ["npx", "-y", "redis-mcp"], - "enabled": true, - "env": { - "REDIS_HOST": "localhost", - "REDIS_PORT": "6379" - } - } - } -} diff --git a/plans/README.md b/plans/README.md index f4584186..3aa56d7f 100644 --- a/plans/README.md +++ b/plans/README.md @@ -1,5 +1,9 @@ # Advisor Plans Index +> **Archive historique — pas un backlog actif.** Ces plans décrivent des +> cycles antérieurs. Ils servent de provenance uniquement et ne doivent pas +> déclencher un travail sans validation contre les sources de vérité actuelles. + This directory holds the forward-looking advisor audits for the GW2Analytics monorepo. Each audit is a senior-advisor survey (improve skill, `next` invocation, `quick` effort) that scopes the next cycle's direction-only diff --git a/pyproject.toml b/pyproject.toml index 6dedb73d..ee161341 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,7 +128,6 @@ extend-exclude = [ # BMAD framework files (third-party) - exclude from linting ".agents", "_bmad", - ".opencode", ] [tool.ruff.lint] diff --git a/tests/scripts/test_bmad_framework.py b/tests/scripts/test_bmad_framework.py index 37ab9f78..dbd0f771 100644 --- a/tests/scripts/test_bmad_framework.py +++ b/tests/scripts/test_bmad_framework.py @@ -11,6 +11,64 @@ ROOT = Path(__file__).resolve().parents[2] BMAD_SCRIPTS = ROOT / "_bmad" / "scripts" SKILLS_DIR = ROOT / ".agents" / "skills" +MANIFEST_PATH = ROOT / "_bmad" / "_config" / "manifest.yaml" +EXPECTED_CODEX_SKILL_COUNT = 49 +# This inventory is pinned to the official BMAD 6.11.0 Codex installation used +# by this repository. Keep it explicit so an installer upgrade cannot silently +# remove a canonical skill or reintroduce a legacy IDE integration. +EXPECTED_CODEX_SKILLS = frozenset( + { + "bmad-advanced-elicitation", + "bmad-agent-analyst", + "bmad-agent-architect", + "bmad-agent-dev", + "bmad-agent-pm", + "bmad-agent-ux-designer", + "bmad-architecture", + "bmad-brainstorming", + "bmad-build", + "bmad-build-auto", + "bmad-checkpoint-preview", + "bmad-code-review", + "bmad-correct-course", + "bmad-create-architecture", + "bmad-create-epics-and-stories", + "bmad-create-prd", + "bmad-create-story", + "bmad-customize", + "bmad-deep-recon", + "bmad-dev-auto", + "bmad-dev-story", + "bmad-document-project", + "bmad-domain-research", + "bmad-edit-prd", + "bmad-editorial-review", + "bmad-editorial-review-prose", + "bmad-editorial-review-structure", + "bmad-forge-idea", + "bmad-generate-project-context", + "bmad-help", + "bmad-market-research", + "bmad-party-mode", + "bmad-prd", + "bmad-prfaq", + "bmad-product-brief", + "bmad-project-context", + "bmad-qa-generate-e2e-tests", + "bmad-quick-dev", + "bmad-retrospective", + "bmad-review", + "bmad-review-adversarial-general", + "bmad-review-edge-case-hunter", + "bmad-review-verification-gap", + "bmad-spec", + "bmad-sprint-planning", + "bmad-sprint-status", + "bmad-technical-research", + "bmad-ux", + "bmad-validate-prd", + } +) FRONTMATTER_RE = re.compile(r"\A---\n(.*?)\n---\n?", re.DOTALL) @@ -46,15 +104,26 @@ def test_bmad_framework_resolve_config_merges_project(): assert "bmad-agent-analyst" in config["agents"] -def test_bmad_skills_frontmatter_is_opencode_loadable(): - skills = sorted(dir_ for dir_ in SKILLS_DIR.iterdir() if dir_.is_dir()) - assert skills, "no skills under .agents/skills/" - for skill_dir in skills: +def test_bmad_skills_frontmatter_is_codex_discoverable(): + skills = {path.name: path for path in SKILLS_DIR.iterdir() if path.is_dir()} + assert len(EXPECTED_CODEX_SKILLS) == EXPECTED_CODEX_SKILL_COUNT + assert set(skills) == EXPECTED_CODEX_SKILLS + for skill_name, skill_dir in sorted(skills.items()): skill_md = skill_dir / "SKILL.md" assert skill_md.is_file(), f"{skill_dir.name}/SKILL.md missing" match = FRONTMATTER_RE.match(skill_md.read_text()) assert match, f"{skill_dir.name}/SKILL.md has no frontmatter" meta = yaml.safe_load(match.group(1)) assert isinstance(meta, dict), f"{skill_dir.name}: frontmatter not a mapping" - assert meta.get("name") == skill_dir.name, f"{skill_dir.name}: name mismatch" + assert meta.get("name") == skill_name, f"{skill_dir.name}: name mismatch" assert meta.get("description"), f"{skill_dir.name}: description missing" + + +def test_bmad_manifest_is_codex_only_without_legacy_opencode_integration(): + manifest = yaml.safe_load(MANIFEST_PATH.read_text()) + + assert manifest["installation"]["version"] == "6.11.0" + assert manifest["ides"] == ["codex"] + assert not (ROOT / ".opencode" / "commands").exists() + assert not (ROOT / "opencode.json").exists() + assert not (ROOT / "opencode.jsonc").exists()