公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-29 17:24 UTC

chuongnd2612 / q-agent

HTML · Python · TypeScript未检测到许可证★ 0 星标⑂ 0 复刻始于 2026年7月在 GitHub 上查看 ↗

chuongnd2612/q-agent 的健康指数为 100 分中的 32 分,处于「存在风险」区间。 其得分最高的类别是AI Readiness(65/100),最低的是Community & Adoption(12/100)。 最近一次更新在 1 天前。 近期的大部分工作由 1 位贡献者完成。

32
总分 / 100
存在风险

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

32
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

Nguyen Dinh Chuong个人账户
0 关注者23 个公开仓库始于 2019年10月

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
npm@q-agent/agent指向其他仓库——不计分0.1.294,037268 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

35存在风险 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 1 天前
2.8/36提交节奏 — 52 周中有 4 周有提交
18/18提交量 — 最近一年 315 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year315
human_commit_share1
days_since_last_push1
active_weeks_last_year4
评分方式
0/27有发布版本 — 未发布任何发布版本
0/36发布时效 — 没有发布版本
0/27发布节奏 — 没有发布版本
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count0
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

12危急 · 占总体的 18%
评分方式
0/60星标 — 0 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

25危急
评分方式
22.5/22.5README
0/22.5许可证 — 未检测到许可证文件
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

41存在风险 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
0/10OpenSSF Scorecard:Contributors — project has 0 contributing companies or organizations -- score normalized to 0
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
41/46.8议题解决 — 88% 的议题已关闭
38.2/38.3PR 接受 — 已裁定的 PR 中 292/292 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs292
open_issues22
closed_issues157
issue_closed_ratio0.877
closed_unmerged_prs0
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
0/25所有者影响力 — chuongnd2612 有 0 位关注者
22.1/25既往记录 — 23 个公开仓库,账户约 6 年
所用输入
followers0
owner_typeUser
is_verified
owner_loginchuongnd2612
public_repos23
account_age_days2,474
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。

工程质量

基础的工程与文档实践是否到位?

36存在风险 · 占总体的 20%

工程实践

24危急
评分方式
0/24CI 工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 0 out of 30 merged PRs checked by a CI test -- score normalized to 0
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

55中等
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
0/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

29危急 · 占总体的 16%

安全态势

11危急
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 0 out of 30 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
0/10Dangerous-Workflow — 无数据
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5许可证 — license file not detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — 无数据
0.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — 无数据
0/7.5Vulnerabilities — 36 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated14
scorecard_versionv5.5.0
checks_inconclusive4
scorecard_aggregate1.1
已排除计分(无数据或不适用):dangerous_workflow, packaging, signed_releases, token_permissions。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories0
affected_packages0
assessed_packages30
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
已排除计分(无数据或不适用):没有长期未处理的公告。 其余权重已重新归一化。 比对的是 npm:@q-agent/agent@0.1.29 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 30 个软件包。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

65中等 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 100 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes8,894
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — agent/tsconfig.json, app/tsconfig.json
10/10可复现环境 — Dockerfile, lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 100 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
1/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
所用输入
has_nix
has_tests
lockfilespackage-lock.json, uv.lock
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsagent/tsconfig.json, app/tsconfig.json
agent_commit_share1
toolchain_manifests
dependency_bot_commit_share0
评分方式
27/45可类型检查的代码 — HTML,已配置类型检查(agent/tsconfig.json, app/tsconfig.json)
53.9/55可控的文件大小 — 采样的 347 个源文件中有 7 个超过 60KB
所用输入
primary_languageHTML
largest_source_bytes68,273
source_files_sampled347
oversized_source_files7

机器可读接口

40存在风险
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_files

关键数据

0GitHub 星标
1贡献者
315最近 12 个月提交数
1距最近推送天数
0发布版本数
1巴士系数(bus factor)
22开放议题
npm, PyPI软件包生态系统数

数据采集警告

  • npm package '@q-agent/agent' points at a different repository (https://github.com/chuongduong2810/q-agent); excluded from ecosystem scoring
  • Could not fetch pypi package 'q-agent-api' from its registry
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

更多细节

OpenSSF Scorecard 1.1 / 10
1.1综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-29 17:24 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 30 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
不适用Dangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
不适用Packagingpackaging workflow not detected
1Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 1
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
0Vulnerabilities36 existing vulnerabilities detected
直接依赖 38
注册表软件包版本约束清单文件
npm@anthropic-ai/claude-code^2.1.0agent/package.json
npm@playwright/test^1.61.1agent/package.json
npmcommander^12.1.0agent/package.json
npmelectron-updater^6.3.9agent/package.json
npmplaywright^1.61.1agent/package.json
PyPIfastapi>=0.115.6api/pyproject.toml
PyPIuvicorn>=0.34.0api/pyproject.toml
PyPIsqlalchemy>=2.0.36api/pyproject.toml
PyPIpydantic>=2.10.4api/pyproject.toml
PyPIpydantic-settings>=2.7.0api/pyproject.toml
PyPIalembic>=1.14.0api/pyproject.toml
PyPIhttpx>=0.28.1api/pyproject.toml
PyPIloguru>=0.7.3api/pyproject.toml
PyPIcryptography>=44.0.0api/pyproject.toml
PyPIpillow>=11.0.0api/pyproject.toml
PyPIpython-multipart>=0.0.20api/pyproject.toml
PyPIwebsockets>=14.1api/pyproject.toml
PyPIargon2-cffi>=23.1.0api/pyproject.toml
PyPIpyjwt>=2.10.0api/pyproject.toml
PyPIpyotp>=2.9.0api/pyproject.toml
PyPIpsycopg>=3.2api/pyproject.toml
npm@tanstack/react-query^5.101.2app/package.json
npmclsx^2.1.1app/package.json
npmcmdk^1.1.1app/package.json
npmdompurify^3.4.12app/package.json
npmframer-motion^11.15.0app/package.json
npmi18next^26.3.6app/package.json
npmi18next-browser-languagedetector^8.2.1app/package.json
npmlucide-react^0.469.0app/package.json
npmqrcode.react^4.2.0app/package.json
npmreact^19.0.0app/package.json
npmreact-dom^19.0.0app/package.json
npmreact-i18next^17.0.9app/package.json
npmreact-router-dom^7.18.1app/package.json
npmsonner^1.7.1app/package.json
npmtailwind-merge^2.6.0app/package.json
npmthree^0.171.0app/package.json
npmzustand^5.0.2app/package.json
全部依赖 未采集

本报告未能采集到解析后的依赖集合:GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

依赖安全公告 0

安装 npm:@q-agent/agent@0.1.29 会引入 30 个包(直接与传递):其中 0 个存在已知公告,0 个为直接依赖。

没有已知公告影响已评估的依赖。

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 11207,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "CSS": 7258,
        "HTML": 1703258,
        "Mako": 868,
        "Shell": 2466,
        "Python": 1529799,
        "Batchfile": 2542,
        "Dockerfile": 3755,
        "JavaScript": 405089,
        "TypeScript": 1273600
      },
      "pushed_at": "2026-07-28T07:46:14Z",
      "created_at": "2026-07-04T09:10:41Z",
      "owner_type": "User",
      "updated_at": "2026-07-28T07:48:02Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "master",
      "license_spdx_raw": null,
      "primary_language": "HTML",
      "significant_languages": [
        "HTML",
        "Python",
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Nguyen Dinh Chuong",
      "type": "User",
      "login": "chuongnd2612",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/56782309?v=4",
      "created_at": "2019-10-20T05:49:31Z",
      "is_verified": null,
      "public_repos": 23,
      "account_age_days": 2474
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [],
      "recent_commits": [
        {
          "oid": "cbcb3eefedffcbe9ac76cdc121333a5d5091d6d3",
          "body": "… (#471)\n\nThe root README was last substantively updated on 2026-07-04 and had drifted\nbadly enough to mislead. It claimed the app was local-first on SQLite with no\ncloud, never mentioned authentication (which is on by default), never mentioned\nthe Local Agent (where execution actually happens), and\n[…]\nare\ndisclosed in the docs so nobody reads a failure as their own.\n\nCloses #468\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: bring README, CONTEXT and api/README up to current state (#468)…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-28T07:46:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "64b9c504bb5101419986ec566b0600192704fb79",
          "body": "…6) (#467)\n\nA project-knowledge build ran in a background thread with no ambient run,\nso resolve_ambient_owner_id() returned None and the Claude call fell back\nto the shared credential — even when the requesting user had an active\npersonal credential. Inconsistent: the same build clones with the own\n[…]\ns\nClaude spend to the owner. Shared builds (owner_id None) still use shared.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(knowledge): build uses the row owner's own Claude credential (#46…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T16:33:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5568899570adc09fe08234ede6a8ed3f2d8c01db",
          "body": "…4) (#465)\n\nlist_repos() only hit /orgs/{owner}/repos, which 404s when the owner is\na personal user account rather than a GitHub organization; the single-repo\nfallback then also 404'd, surfacing \"Could not list repos: 404\".\n\nAdd _discover_owner_repos: org listing first, then fall back to the\nauthent\n[…]\nured\nrepo as a last resort. Covers org, personal, and repo-scoped-PAT cases.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(github): discover repos for personal accounts, not just orgs (#46…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T16:18:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "13540a579a79465760e0bedba0d110c8e88b4f6c",
          "body": "…ad loader (#463) (#463)\n\nThe Video tab showed \"No video captured\" on a run where video was simply not\nrecorded — video is gated on the \"Capture video\" setting (default off), so that\nmessage was misleading (read as \"still uploading\").\n\n- Video empty-state is now 3-way: uploading → loader; capture of\n[…]\nelease to emit exec.evidence.uploading; the video-off explanation works now.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(evidence): explain empty Video tab (capture off) + per-panel uplo…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T16:07:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f395472d76314594e1641c58d26734202a834506",
          "body": "…u (#462) (#462)\n\nThe standalone amber eraser sat right next to the menu (which already had a\nredundant Cancel), cluttering the run header. Move the function into the menu:\n\n- RunActionsMenu: the old \"Cancel\" (non-terminal only) becomes a terminal-aware\n  Stop/Clean-up item shown for ANY status, usi\n[…]\nlabels: actions.stop / actions.cleanup.\n\nFrontend-only (docker rebuild web).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(runs): fold the Stop/Clean-up control into the three-dot men…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T11:42:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ac0b8b2beb62f3ed759b1b651b5384c8f56d82f4",
          "body": "…nce (#460) (#461)\n\nThe Local Agent reports results immediately, then uploads evidence in a detached\ntask after the run is marked done — with no WS event. So the Evidence panel showed\nempty right after a run, and its query (a separate key useRunSocket never\ninvalidated on exec events) never refreshe\n[…]\nNo server change — push_job_event\nalready relays these events to the run WS.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(evidence): loader while the agent uploads a finished run's evide…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T11:32:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ebeaf85b2afe2de4c7b8602f98daa98f84884fb",
          "body": "…efreshes (#458) (#459)\n\nServer calls already rotate the stored credential (run_prompt → persist_refreshed).\nThe gap was the Local Agent path: live-authoring/heal runs `claude` with the\nowner's credential in a temp config dir, the CLI rotates the OAuth token (and often\nthe refresh token) there, then\n[…]\neal (same pipeline).\n\nServer (docker rebuild api) + agent (pending release).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(creds): auto-rotate uploaded Claude credential from agent-side r…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T11:21:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "56be5a414d330c5f98a5aad39a8e3ef242bc5f5b",
          "body": "…l network + console capture (#456) (#457)\n\nEvidence after a run was incomplete: screenshots were hardcoded\nonly-on-failure, the \"Capture video\" setting was a dead toggle, and the\nNetwork/Console tabs were structurally always empty (columns surfaced but\nnever populated).\n\n- Screenshot: `screenshot: \n[…]\nalready\nexist (no migration). UI already renders the console/network shapes.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(evidence): always-on screenshot, video honoring the setting, rea…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T10:37:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "721fa1c42ca8d85e084e4da8c9419d44deb74599",
          "body": "… (#455)\n\nComments were built purely from result facts, so they used generic wording. Now\nprepare_comments resolves the run's project once (_resolve_project_for_run →\nproject_key + env base_url), loads the best ProjectKnowledge row, and injects a\nconcise \"Project context\" block (environment URL, dom\n[…]\n the provided context, don't read files).\n\nServer-only (docker rebuild api).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(comments): ground ticket comments in the run's project KB (#454)…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T10:25:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fb1acafca56566dbec716bfbe53552d3b7f52e9f",
          "body": "…g into comments (#452) (#453)\n\nNot a Docker regression — the KB is persisted in the workspace volume. The comment\ngenerator passes facts inline and never points Claude at the KB, but the skill\ntold Claude to read a knowledge.md; Claude narrated its absence and that preamble\nprepended the comment bo\n[…]\n comments; existing\nones can be re-prepared or edited in the comment editor.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(comments): stop Claude preamble (\"No knowledge.md found…\") leakin…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T10:16:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2c46bb99489921f40e18d30744fb58f50d722a45",
          "body": "…450) (#451)\n\nThe Publish screen showed the AI comment body as raw text (literal **bold**, ---,\n- lists) with no way to edit before publishing.\n\n- New dependency-free MarkdownLite renderer: renders the comment markdown subset\n  (paragraphs, ---, headings, bullet lists, fenced code, inline bold/itali\n[…]\ntrings.\n\nFrontend-only (docker rebuild web) — edit endpoint already existed.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(comments): edit + markdown-preview editor for ticket comments (#…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T10:09:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e19b5ad1e28ca095abcad1a450e28aeaa84752ef",
          "body": "…#449)\n\nThe one-shot left→right shine sweep replayed on every hover across glass\nsurfaces was distracting. Remove all usages (GlassCard, Dashboard hero,\nDropdown) plus the sweep-replay state, and delete the TiltSweep component.\nHover brighten, Dashboard tilt, and the /runs·/tickets·/settings lift are\nunchanged.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): remove the Shine Sweep (TiltSweep) glass animation (#448) (…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T10:06:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0810aa1c9af600becfcf6c18002f9d539a7e80a9",
          "body": "…event) (#446) (#447)\n\nTraced from api logs: \"Claude CLI exited -9\" (SIGKILL) at 0.0s → 502. RUN-200 was\ncancelled, so its in-memory run_control cancel event was still armed (only cleared\non retry/delete). prepare_comments runs a synchronous Claude summarize attributed\nto the run, and run_prompt's r\n[…]\nm killing a legitimate later Claude call.\n\nServer-only (docker rebuild api).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(comments): Prepare comments 502 on a cancelled run (stale cancel …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T09:58:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d6e24520c943e0cb96140d77347635cdec33de2a",
          "body": "…4) (#445)\n\nWhen connected but idle / just reconnected (buffer empty), showConnected cleared\nthe log and the SSE replay had nothing to show, leaving a blank panel that reads\nas broken. Seed a placeholder (\"Ready · waiting for activity… — Runs,\nlive-authoring and self-heal will stream here.\") on conn\n[…]\nog\nline removes it.\n\nAgent-only (ui.ts) — ships with the next agent release.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(agent): empty-state for the AGENT LOG instead of a blank box (#44…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T08:55:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2448eaf7671f5abc8af916e523ce4dd96c547409",
          "body": "…al run (#442) (#443)\n\nThe agent finished authoring (spec written) but the web trail stayed stuck on\n\"authoring…\" because finalize_authored_spec dropped the post-back for a terminal/\ncancelled run (the #419/#420 guard). That left the spec at status=\"running\", and\nauthoringActive keeps the trail spin\n[…]\nregenerated publish lets the trail close.\n\nServer-only (docker rebuild api).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(authoring): don't strand a finished spec as \"running\" on a termin…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T08:45:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0a9f24354d02edcffdc9e0a8fe7ebdef07b8bacf",
          "body": "…#441)\n\nMirror the web trail's Authoring log detail setting in the desktop AGENT LOG.\nThe agent doesn't know the server setting, so thread it through the authoring job:\n- Server: authoringLogVerbosity → request_authoring(log_verbosity) → _pending →\n  AuthoringClaimOut.log_verbosity (POST /agent/auth\n[…]\nsts).\n\nServer (docker rebuild api) + agent (ships with the pending release).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): AGENT LOG respects the concise/verbose Settings (#440) (…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T08:32:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c16d6cb3bf76dd3c0f4202282e4402af05a352b3",
          "body": "…ray on close (#438) (#439)\n\n1. AGENT LOG now shows live-authoring / live-self-heal steps. The runner already\n   emits per-step `authoring-step` events into the bus (buffered + SSE-streamed to\n   the desktop UI), but ui.ts had no logMsg case for them, so the panel stayed\n   empty during a session. A\n[…]\nmain.cjs + ui.ts) — ships with the next agent release; no\nserver/web change.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): live-authoring/heal log in AGENT LOG + keep running in t…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T08:07:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "982a1bfc119f33368fa80a2f6c440b84ed5f67ba",
          "body": "…d-flight abort (#436) (#437)\n\nFollow-up to the per-run Stop (#420):\n\n1. Stop now clears the \"authoring…/working…\" trail. _stop_run_work publishes a\n   terminal authoring.progress (phase failed) + spec.regenerated for each spec it\n   resets, so an open client flips back to the (now draft) editor ins\n[…]\nease.\n\nServer + web (docker rebuild) deliver 1–2; 3 is agent-side (release).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(runs): Stop clears the live trail + in-run Stop button + agent mi…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T07:45:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b6b1c582fba05b5b0d53bd10223ba9f9ede32bc0",
          "body": "…ow (#434) (#435)\n\nThe height-collapse animation needs overflow:hidden, but that cropped the\nGlassCard hover-lift shadow/glow (#430) on open sections. Switch overflow to\n`visible` once a section's open animation settles (hidden while\ncollapsed/animating), so open sections no longer clip child shadows.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(settings): stop CollapsibleSection clipping child hover-lift shad…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T07:28:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "78e25b31347197fcfabae0d2e8f82969df94c006",
          "body": "…cl. tilt/lift tweaks (#430) (#432)\n\n* feat(ui): reduce tilt strength, restrict tilt to Dashboard cards, hover-lift on /tickets & /settings (#430)\n\n- useTilt: gentler defaults (4°/5° / scale 1.02 / perspective 1000)\n- GlassCard: `tilt` now opt-in (default off) + new opt-in `lift` (raise + shadow)\n- \n[…]\nAuthored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): live-session budget + collapsible sections (#431); in…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T07:19:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d49e8ecd944f5f98cd57bd7a21823e370cc59bc",
          "body": "…er-lift on /tickets & /settings (#430) (#433)\n\n- useTilt: gentler defaults (4°/5° / scale 1.02 / perspective 1000)\n- GlassCard: `tilt` now opt-in (default off) + new opt-in `lift` (raise + shadow)\n- Dashboard: opt its cards back into the (reduced) tilt\n- Tickets: hover-lift rows matching /runs\n- Settings: swap tilt for hover-lift\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): reduce tilt strength, restrict tilt to Dashboard cards, hov…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T07:13:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c46fe0806788213bfa8d19711ac259b0c43343d9",
          "body": "… pipeline (#428) (#429)\n\nAdds a configurable Self-heal mode alongside Authoring mode:\n- \"classic\" (default) — the existing generate-a-fix + re-run-Playwright loop.\n- \"live-harness\" — drive the REAL app with browser-harness (Claude agentic, like\n  live-authoring): reproduce the failure, find the rea\n[…]\ngent release for\nbrowser-harness + claude on the device (no NEW agent code).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(heal): browser-harness self-heal mode reusing the live-authoring…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T06:31:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8700adf90ce56e35bff88b60920cf68afdfa1398",
          "body": "…trail (#426) (#427)\n\nThe live-authoring step log showed raw tool lines (▷ Bash: browser-harness <<'PY'\n… PY) that confuse end users, and didn't follow the newest line.\n\n- New workspace setting authoringLogVerbosity (\"concise\" default | \"verbose\"):\n  settings_store default + SettingsOut/SettingsUpda\n[…]\noth message kinds). Server + web\n(docker rebuild) — no agent release needed.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): concise/verbose authoring-log setting + auto-scroll …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T04:44:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "db13e99e3a9f48a1d78708834710047f5b41d603",
          "body": "…ot grey) (#425)\n\nThe per-run Stop control renders on every row, but for terminal runs it used a\ngrey icon (text-ink-soft on bg-white/[0.05]) sitting between the grey open (→)\nand menu (⋯) buttons, so it blended in and read as missing. Give the terminal\n\"force clean up\" state an amber tint (#f59e0b) so it's clearly findable and\ndistinct from the red in-progress Stop.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(runs): make the terminal \"clean up\" Stop button visible (amber, n…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-21T02:59:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "01814c4cf3bfc48dcb2360406be864a7b416a5d1",
          "body": "…up\" (#420) (#424)\n\nFollow-up to the per-run Stop button: it was gated to in-progress runs only, so\nwhen there were no active runs the button was invisible and looked missing.\n\n- The button now shows on EVERY run row:\n  - In-progress run → red Stop (■): cancel the run + all in-flight work.\n  - Termi\n[…]\nare confirm\n  dialog + toast; en/vi strings.\n\nServer + web (docker rebuild).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): show Stop on every run; terminal runs get a \"force clean …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T11:09:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4f897e9b7df99a148c0df2f19f006e55d9d16fb0",
          "body": "…421) (#423)\n\nAdd windowsHide:true to the two remaining direct spawns that could pop a\nconsole window on Windows when the agent runs as a GUI (Electron) process:\n- ensureTooling.run() — uv download/extract + `browser-harness --version` probe\n  + `uv tool install` (one-time browser-harness provisioni\n[…]\nent change — requires `cd agent && npm run release` to reach paired devices.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(agent): hide console windows for first-run provisioning spawns (#…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T10:48:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12baa39cf4371900310cf2e1fbf23e2e1f115399",
          "body": "…uthoring re-run (#419, #420) (#422)\n\n#420 — Stop a run and everything it's doing:\n- Add a prominent per-row Stop button on the Runs list (non-terminal runs),\n  confirm dialog → useCancelRun. i18n en/vi.\n- Extend cancel_run with _stop_run_work: after flipping the run to 'cancelled'\n  and killing tra\n[…]\nabort (agent\npolling a cancel flag) is a follow-up needing an agent release.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): per-run Stop button + full in-flight cleanup; fix stale a…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T10:47:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a9b8d33a891bcd48f4a8c5c2b36b7e320e3699bc",
          "body": "…ze as a step) (#418) (#418)\n\nAnalyze (Run.status \"processing\") is the automatic auto-analysis lead-in to\nReview, not a user step. It was already dropped from the desktop sidebar nav,\nbut the shared stage numbering still started at 2 for Review — so the vertical\npipeline showed Review as \"2\", which \n[…]\n- RunContextHeader \"stage N of {total}\" now reads \"of 6\" (total is dynamic).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(pipeline): number the run pipeline from Review=1 (drop Analy…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T09:54:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e699a961112e8735c32949befad6dd34945d476d",
          "body": "Apply the run-sidebar feedback on the honest 7-stage pipeline:\n\n- Highlight the active step: currentStage now falls back to failedStage,\n  so a failed/cancelled run still lights the stage it stopped at instead\n  of nothing.\n- Drop the \"Analyze\" entry from the sidebar pipeline nav — it has no\n  sub-r\n[…]\nreen — a whole run is searchable by\n  its code in the global Audit Log page.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(run-nav): tidy run workspace sidebar (#417) (#417)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T09:31:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b49c877de599a1669c76207ea7220df95adf1c6c",
          "body": "…pper (#416)\n\nSync & Select happen before a run exists (global Tickets sync + Create-Run\nselection), so they had no backing Run.status — their \"completed\" was faked\n(green for any live run, grey when cancelled/failed). And the three per-run\nsurfaces disagreed (top rail 9, sidebar 8, mobile 7).\n\nMake\n[…]\not the per-run stepper.\n\nVerify: app typecheck + build clean. Frontend-only.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): honest 7-stage pipeline — drop Sync & Select from the ste…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T09:09:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "584297f274439459e8abc49381b4a56a243f6b3d",
          "body": "…I) (#415)\n\nEvery exec.* event invalidated + REFETCHED the execution query, so a spec's\nstatus dot only flipped after a network round-trip. Apply exec.case.result\n(per-row status/duration) and exec.progress/exec.done (counts/progress) straight\nto the execution cache via setQueryData so the UI update\n[…]\nof\nrun-end — needs the agent release.)\n\nVerify: app typecheck + build clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(exec): apply exec results to the cache optimistically (instant U…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T08:42:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e873bbbc7e7369a845451435f7dd8e454a2bc99a",
          "body": "…) (#exec-live) (#414)\n\nExecution status updated in a burst at the very end: the agent ran the whole\n`playwright test`, parsed report.json, then posted every result at once. The\nserver relay + UI are already per-result/instant — only the agent batched.\n\nAdd a vendored Playwright reporter (live_repor\n[…]\nDocker rebuild.\nVerify: agent tsc + `node --test dist/test` (40 pass) clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(agent): stream per-spec execution results live (immediate status…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T08:28:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4120cc21f790551e565ce24bcb6cfccb605e95be",
          "body": "…nel) (#400) (#413)\n\nThe captured authoring cost was only shown in the top banner header (which is\nhidden when the authoring spec is selected) and the in-panel trail's final line\n(which vanishes when the code replaces it) — so it was effectively invisible.\n\n- Completion toast: on the terminal author\n[…]\ne it belongs.\n\nVerify: app typecheck + build clean; server py_compile clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): make the authoring cost visible (toast + run cost pa…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T08:04:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "03c49a9180ba2bee2566492ce2fe56cea422241b",
          "body": "A spec row that exists but has no code yet rendered a blank one-line editor\n(a lone \"1\" gutter). Show a friendly \"Not generated yet\" empty state in the code\npanel instead when the selected spec's code is empty and it isn't being authored\nor edited. Adds spec.empty.{title,hint} (en + vi). Frontend-only.\n\nVerify: app typecheck + build clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(automation): empty-state for a not-yet-generated spec (#400) (#412)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T07:18:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "39c6b7525b8f671df82df588f708214fb13a35cc",
          "body": "…(#400) (#411)\n\nThree live-authoring bugs:\n\n1. Premature \"Regeneration finished\" toast. The async enqueue publishes a PENDING\n   (status=\"running\") spec.regenerated immediately, then the real authored spec on\n   a later terminal event. The handler showed completion feedback for the pending\n   one. F\n[…]\nrify: agent tsc clean; app typecheck + build clean; server py_compile clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(authoring): premature toast, empty editor, and flashing terminal …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T07:00:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "996c7ea772d52d8c1cfc6a54b97b10e6f2555327",
          "body": "…g cost (#400) (#410)\n\nWhile Live authoring runs the spec is status=running with empty code, so the code\npanel rendered a blank \"1\"-line editor. And the agentic Claude runs on the agent,\nso its $ cost was invisible server-side.\n\nEditor state:\n- ProgressBanners: extract a reusable AuthoringTrail (str\n[…]\nrify: agent tsc clean; app typecheck + build clean; server py_compile clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): live trail in the spec editor + surface the authorin…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T06:46:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "641ac19757f08c8273ccf4b1a6e877bc29d544ac",
          "body": "* fix(authoring): pass prompt as arg + stream steps live so Claude actually drives (#400)\n\nTwo problems: (1) the task prompt was piped via stdin, but headless `claude -p`\nreads the prompt from argv — so Claude got no task and exited doing nothing\n(\"complete\", no spec); (2) there was no visibility in\n[…]\nAuthored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "bug/authoring drive and stream (#409)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T05:29:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fdb6154986a316287cedce49c2f5cf64b62388b0",
          "body": "…in page) (#408)\n\nThe launcher started Chrome with baseUrl on the command line, so Chrome navigated\nto the app immediately — before the sessionStorage replay was armed. MSAL/SPA apps\nfound no token in sessionStorage and rendered the login page; browser-harness then\nattached to that already-loaded lo\n[…]\ny the restored session).\n\nVerify: launcher node --check clean (both copies).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(authoring): restore session BEFORE the app loads (was showing log…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T04:46:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "285a3a7f7870213fcb1ac4fcb0e23b0249847751",
          "body": "…) (#407)\n\nMake the Local Agent self-contained for live-authoring so users don't hand-install\nthe two prerequisites.\n\n- claude: add @anthropic-ai/claude-code as an agent dependency (bundled by the\n  Electron build / npm install). paths.claudeCli() resolves the package's native\n  `bin/claude[.exe]`; \n[…]\nerify so far: agent tsc build clean; claudeCli() resolves the native binary.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): bundle claude CLI + auto-provision browser-harness (#400…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T04:14:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1ee4f7c89e7a5f29e45e7385d65cbedb6217ab0b",
          "body": "…henticated (#400) (#406)\n\nThe authoring launcher reused the capture browser-profile (cookies + localStorage)\nbut never replayed sessionStorage. MSAL/SPA apps (e.g. hub-dev) keep their auth\ntoken in sessionStorage, which is never persisted to a Chrome profile on disk — so\nbrowser-harness's browser l\n[…]\non is restored.\n\nVerify: agent tsc build clean; launcher node --check clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(authoring): replay saved sessionStorage so browser-harness is aut…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-20T02:49:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "573df993e70cab28aacaaf3455e23803c58efae7",
          "body": "… (#400) (#405)\n\nLocal-agent live-authoring previously required a separate `claude login` on the\nagent machine. Instead, hand the agent the run owner's effective saved\ncredential (own → shared, the same precedence the server uses) so its local\n`claude` authenticates with the credential uploaded in S\n[…]\n live on the\nagent.\n\nVerify: agent tsc build clean; server py_compile clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): reuse the app's saved Claude credential on the agent…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-17T12:44:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "64fe2878e7a8d6c63687829d3eb22438428450a7",
          "body": "browser-harness must run co-located with Claude. When executionTarget is\nlocal-agent, run the whole live-authoring loop on the paired machine (where\nbrowser-harness, Chrome, the authenticated sessions, and the claude CLI all\nalready live) instead of server-side — no Docker/headless-MSAL friction.\n\nS\n[…]\ne for the origin.\n\nVerify: agent `tsc` build clean; server py_compile clean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): run live-authoring on the Local Agent (#400) (#404)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-17T12:20:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d6f0825da80eee34ed95c4f971c6d4449378c3d4",
          "body": "…#403)\n\nbuild_context always set context[\"baseUrl\"] = cfg.base_url (even \"\" when the\ntop-level Base URL field is empty), so the intended `setdefault(..., kn.base_url)`\nKB fallback never fired — a project whose base URL lived only in the Knowledge\nBase surfaced as no base URL. This broke live-authori\n[…]\ned when the config\nfield is blank; a real configured/per-env URL still wins.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(context): use KB base_url when the ProjectConfig field is blank (…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-17T12:17:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7c376fb8b7af59ea916c5c4745adb1bf241d22ed",
          "body": "…e (#400) (#402)\n\nLive-authoring drives browser-harness from the API process, so the API\nhost needs browser-harness + a Chrome. Bake them into the API Docker image\nso server-side live-authoring works in the container.\n\n- api/Dockerfile: apt-install chromium, `uv tool install browser-harness`\n  to /u\n[…]\nADR 0012: record the image provisioning + the auth-profile-in-volume caveat.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(authoring): provision browser-harness + chromium in the API imag…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-17T10:45:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "892fc180471a3649f2f3aff3be392c19603900b8",
          "body": "…rtup guard (#401)\n\n* feat(authoring): live spec-authoring via browser-harness (#400)\n\nAdd an opt-in authoring mode that inverts the blind-gen+heal flow: drive\nthe real app first with the browser-harness CLI (via an agentic Claude),\ndiscover real selectors on the live DOM, create any missing test da\n[…]\nagent@cursor.com>\n\n---------\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "feat(authoring): live spec-authoring via browser-harness + dev-db sta…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-17T10:15:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "28f7b86fa15dfa9e65f7b7b8d1675ca180f809ab",
          "body": "… DOM (#398) (#399)\n\nSelf-heal ran 2-4 min. It wasn't the prompt (already bounded); wall-clock was\ndominated by up to 3 sequential attempts, each stalling the full 30s per-test\ntimeout on the broken locator, then a fix call on the heavy Sonnet model.\n\n- Shorter heal re-run timeouts: new heal_test_ti\n[…]\nconfig/fixtures/heal) green; agent `npm run build` + node --test\n(40) green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(heal): fail-fast timeouts, Haiku fixer, lighter evidence, robust…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T09:44:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "45f721a212aaccab77bc75085877921176428127",
          "body": "… (#396) (#397)\n\nThe run Activity view showed only summary counts for an exploration (\"repeat ·\n2 steps · 0 routes, 1 selector · KB updated\"). The step log was sent to finalize\nand dropped, so you couldn't see what the exploration actually did, what it\nretrieved, or what it wrote to the KB.\n\n- audit\n[…]\ny (13, +1 new) + exploration suites green; frontend\ntypecheck + build green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): show exploration step trail + discovered routes/selectors…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T07:18:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d7ffad4d73743af5cb0cc57683e2c3abc3a0723e",
          "body": "…s (#394) (#395)\n\nYou couldn't trace what happened in a run: exploration results lived only in an\nin-memory dict (lost on restart), the Claude-activity panel is global+ephemeral,\nand failures (AI-pipeline crash, explore decide-error/unreachable, Claude 401)\nonly hit the container logs — never the au\n[…]\nailures (execution/explore_api\nsubprocess+thread tests) unchanged vs master.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): per-run activity log — persist & surface run-scoped event…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T07:00:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cbeeef59af15c213637d839e1a12fa85fe928922",
          "body": "…ds (#392) (#393)\n\n\"Explore to unblock\" reused only the saved storageState.json and dropped the\nsibling sessionStorage.json (MSAL/SPA auth tokens that Playwright's storageState\ncannot persist). On an MSAL/SPA target the explore browser therefore booted\nunauthenticated and bounced to login, so the ta\n[…]\n\nexplore, and typing test-account credentials into a login form (read-only).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(explore): replay saved sessionStorage so Explore reuses saved cre…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T05:07:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "69e4fb3d80469f635090f195ada0a80aa9f3748c",
          "body": "Wire useTilt + TiltSweep into DropdownShell so the portalled floating\npanel follows the cursor with the same subtle 3D tilt and shine sweep as\nGlassCard. Tilt is gentled (maxX 6 / maxY 8 / scale 1.015) so option text\nstays readable; tilt.style owns the transform while fixed positioning and\nthe opaque glass background sit alongside it.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): glass tilt effect on dropdown panel (#390) (#391)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T04:42:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "08bf869fa3c0e954c95e43b622bec02d0f40e8ee",
          "body": "…(#388) (#389)\n\nThe public sign-in routes were top-level siblings of the RequireAuth-gated\napp, so a logged-in visitor could open /login (or /forgot) and see the form.\n\nAdd a RedirectIfAuthed guard (inverse of RequireAuth) wrapping those two\nroutes: it bootstraps the session from the refresh cookie \n[…]\ns the session on mount; guarding it would bounce the user\nback into the app.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): redirect authenticated users away from /login and /forgot …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T03:26:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f2ad7b9ce34d85cc47f06d29c02e05fec0158866",
          "body": "…387)\n\nRun rows previously only shifted border color on hover. Add a Framer\nwhileHover that lifts the row (y: -4) and expands its shadow with an\neased 0.25s transition, raising zIndex so the lifted row sits above its\nneighbors. List rows keep a plain lift rather than GlassCard's top-pivot\ntilt — better read for a flat list.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): smooth lift + shadow expansion on run-row hover (#386) (#…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-16T03:15:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0c7cf6f164cc70860c3ee3ed11dab41d07e9f728",
          "body": "…(#385)\n\nWave-2 cleanup: translate the module-scope label maps the wave-1 slices\ndeferred (run-status pills, approval/exec pills, product-defect, knowledge\nstatus + build-overlay steps, relative timestamps).\n\n- New `status` namespace (en+vi), auto-loaded like the others.\n- runStatus.ts: runRateLabel\n[…]\nranslation, so they re-render on switch.\nGate: typecheck + build both green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): shared status labels → `status` namespace (EN/VI) (#384) …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:39:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7ea219b8d3840e0c0349e6f8546867e9c0307252",
          "body": "…(#366) (#383)\n\nWave 1 content slice for #363: add the `settings` translation namespace\n(en + vi catalogs) and route every user-facing string in the Settings\nscreen, admin Settings sub-screens (UserManagement, ClaudeCredentials,\nSharedWorkspace, SharedProjectSettings), and settings components\n(Provi\n[…]\n, GitHub, Playwright) and\n  data/identifiers left untranslated per ADR 0011.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): translate Settings screens to en/vi (settings namespace) …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:24:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7562f1c50479ae2907227747fe33c3d027a527ec",
          "body": "Extract all user-facing strings across the pipeline screens (Automation,\nExecution, Evidence, Comment/Publish, Create & Link) into the `pipeline`\ni18next namespace with English + Vietnamese catalogs (288 keys each).\n\n- Add app/src/i18n/locales/{en,vi}/pipeline.json (auto-loaded by import.meta.glob)\n\n[…]\n attrs left untranslated\n\nGate: npm run typecheck + npm run build both pass.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "i18n: pipeline screens → `pipeline` namespace (EN/VI) (#371) (#382)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:16:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "350bae0569783c580e77c2a353e215642a0c51c0",
          "body": "…5) (#381)\n\nWave 1 content slice for #363. Replaces every user-facing English\nstring across the auth surface (Login, MFA, Forgot/Reset, SignedOut,\nProfile + its modals, shared auth layout/fields) with `t()` keys and\nadds the `auth` namespace catalogs in English and Vietnamese.\n\n- New: app/src/i18n/l\n[…]\nceholders are kept.\n\nGate: `npm run typecheck` + `npm run build` both green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "i18n(auth): externalize auth strings to `auth` namespace (EN/VI) (#36…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:13:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12590324fe0b632e476dc75c050e2df05c36dc62",
          "body": "Extract every user-facing string across the Projects screen, Project Detail\n(overview/knowledge/settings tabs), and the shared-projects catalog into a new\n`projects` i18next namespace, with English + real Vietnamese catalogs.\n\n- Add app/src/i18n/locales/{en,vi}/projects.json (identical nested keys).\n[…]\n.\n- No shared files touched (i18n/index.ts, main.tsx, App.tsx, shell/, ui/).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "i18n: projects namespace (EN/VI) (#368) (#379)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:13:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2c6f0b1770b9d979839f4215fb5dd6d86e8dfe62",
          "body": "…I) (#370) (#380)\n\nWave 1 content slice for #363. Adds `en/runs.json` + `vi/runs.json` and\nroutes every user-facing string in Runs, RunDetail, ReviewCenter,\nRunActionsMenu, and RunBulkBar through `useTranslation(\"runs\")`.\n\nRun-status label words (RUN_STATUS_LABEL, runStatus.tsx badge labels) are\nleft as-is per the slice's out-of-scope carve-out.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "i18n(runs): externalize runs+review strings to `runs` namespace (EN/V…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:12:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "28beb7cc4775327ef9ee53ce4f3cf7e4df1fdaba",
          "body": "…d, Local Agent (#367) (#378)\n\nWave 1 content slice for #363. Extracts every user-facing string in the\nDashboard, GettingStarted, and LocalAgent screens into the `dashboard`\nnamespace (en/vi), with real Vietnamese translations. Embedded-markup\nstrings (bold/code) use <Trans>; run-count/report-count use i18next plurals.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): dashboard namespace (EN/VI) for Dashboard, Getting Starte…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:10:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2f3e7344bec4c1653519ad939833d8704fefc583",
          "body": "Extract every user-facing string on the Reports and Audit Log screens into\nthe new `reports` i18n namespace (EN source + real Vietnamese), per ADR 0011.\n\n- Add app/src/i18n/locales/{en,vi}/reports.json (auto-loaded by the config).\n- Reports.tsx and AuditLog.tsx now use useTranslation(\"reports\") with\n[…]\n  Q-Agent product name.\n\nGate: npm run typecheck + npm run build both green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): reports+audit → `reports` namespace (EN/VI) (#372) (#377)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:08:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "55f5c625cdcc0893fdeead268d21c5d93169093c",
          "body": "Extract all user-facing strings in the Tickets screen, Ticket Detail\nscreen, and SyncTicketsModal into a new `tickets` i18n namespace and\nwire them through `useTranslation(\"tickets\")`. Adds EN + VI catalogs\nwith identical nested keys; reuses `common:cancel`.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): tickets namespace (EN/VI) (#369) (#376)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:06:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1f5019496e8fc5d3708da3c63b1a36b14913765b",
          "body": "…73) (#375)\n\nExtract every user-facing English string in the command palette, the app\ntoast, and the shared `components/ui/**` primitives into a new `commands`\ni18next namespace, with full Vietnamese translations.\n\n- CommandPalette: command labels/descriptions, section headings, search\n  placeholder\n[…]\nts status labels live\nin exported color-map tuples consumed by other slices.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "i18n: commands + shared-ui strings → `commands` namespace (EN/VI) (#3…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T18:04:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f80485f6b5c12a560e0c846e7aacf0640d77dfdb",
          "body": "…(#374)\n\nGreenfield i18next + react-i18next + browser language detector (ADR 0011).\n- src/i18n: init with import.meta.glob auto-loading locales/<lng>/<ns>.json,\n  localStorage-persisted preference (qagent.lang), EN/VI, fallback en.\n- common + nav namespace catalogs (en + vi).\n- LanguageSwitcher (EN|\n[…]\ntheir own\nwithout editing shared config. Gate: typecheck + build both green.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(i18n): foundation — config, EN/VI switcher, shell chrome (#364) …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:52:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a7d0ae41ec85a81659a55f55b9939cc4c8fd7115",
          "body": "…on (#362)\n\nRecord the decision to adopt i18next + react-i18next with a client-only\nlocalStorage language preference and per-feature namespace catalogs\nauto-loaded via import.meta.glob (the split that makes content slices\nfile-disjoint and parallel-safe). Add Locale and Translation-namespace\nglossary entries to CONTEXT.md.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(i18n): ADR 0011 + glossary for EN/VI frontend internationalizati…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:40:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1bab29e3c67d8c5f37022e2b3d6ccdf3b87751c9",
          "body": "…#360) (#361)\n\nDiagnostic logging revealed three defects in agent-driven exploration:\n\nA. decide crashed on step 2 with KeyError 'step' — _build_decide_prompt\n   assumed each history entry has 'step'/'observedUrl', but the Local Agent\n   sends {action,args,reasoning}. Number by position and use .get\n[…]\nd + node --test (40), normalize_discovered mapping, driver run.\n\nCloses #360\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(explore): step-2 KeyError, empty KB write, and headless browser (…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:16:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "701640453cbdcb81086ff4857944e233c97d4716",
          "body": "The shine band was near-vertical. Switch the gradient to 135deg (band runs at a\n45° diagonal) over a full-cover layer translated left→right, and slow the pass\nfrom 0.85s to 1.2s.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ui): 45° diagonal glass sweep, a bit slower (#358) (#359)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:08:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7344dd724ca7dbacdd463c81272dd53ee211ac1b",
          "body": "…sis (#357)\n\nThe agent-driven exploration ends after one step; access logs show a valid\n(non-malformed) decision, so the model is emitting `done` at step 0. Add\ninfo logs of the model's chosen action + reasoning (with observed url +\nelement count) and the finalize summary (stopReason/steps/discovere\n[…]\n exactly why it stops. Uses the\nalready-imported logger; behavior unchanged.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(explore): log the decide decision + finalize outcome for diagno…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:04:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b9df97ddd1857c319ddb28d2b9ca6629064fd055",
          "body": "…) (#356)\n\nReplace the cursor-tracked radial glare with an automatic one-shot diagonal\nlight sweep that travels left→right across the card and replays on each\nhover-enter.\n\n- New TiltSweep: a soft-light diagonal band clipped to the rounded shape,\n  animated once per mount; GlassCard + the Dashboard \n[…]\nl hover glare it replaces).\n\nThe EMESOFT logo's metallic sheen is unchanged.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): glass reflection as a left→right shine sweep on hover (#355…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T17:02:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "33eaf6556e37f8b34368fbfd391b80827c43c80e",
          "body": "…tep (#353) (#354)\n\nThe agent-path decide compared the run's cumulative Claude spend against\nexplore_cost_budget_usd with no baseline, so any run that had already done\nanalysis/generation (far over $0.50) tripped the ceiling on the first\ndecide → {stop: budget} → the loop stopped after one step with\n[…]\n Server-side only — ships via docker rebuild, no agent release.\n\nCloses #353\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(explore): cost budget charged whole-run spend, stopping after 1 s…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T16:54:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3f789f55e03a5653c9d7321fe7de1f0e2d247bde",
          "body": "Extend useTilt to expose the springed cursor position (px/py, 0–100%) and a\nhover `glow` (0→1) so lighting overlays track the pointer in lock-step with the\ntilt (reduced motion keeps everything inert).\n\n- Glass reflection: new TiltGlare overlay — a cursor-tracked radial sheen\n  clipped to the rounde\n[…]\nthe\n  transparent background), screen-blended, sweeping as the cursor moves.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): metallic lighting + glass reflection on the tilt (#351) (#352)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T16:51:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8d09a2f19aa99c8639041a365a56d405c546a864",
          "body": "…e.accessibility (#349) (#350)\n\nThe exploration driver called page.accessibility.snapshot(), which is\nundefined in the Playwright version the agent ships, so every observe()\nthrew and the loop broke at step 0 → \"claimed → complete\" with zero\ndecide calls and nothing discovered.\n\n- explore_session.cj\n[…]\nth a\nnon-empty aria tree; agent build + node --test (40) green.\n\nCloses #349\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(explore): observe() crashed — use ariaSnapshot(), not removed pag…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T16:37:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d325e229bcc6148fb0b739f23bb88a67c6992ad1",
          "body": "…finalize + dispatch (#337) (#340)\n\nServer side of agent-driven exploration (epic #336): run the DOM\nexploration loop on the paired Local Agent instead of the server.\n\n- agent_explore_service.py: in-memory pending-session queue + terminal\n  result/status store (mirrors agent_capture_service).\n- rout\n[…]\n path too.\n- schemas.py: agent-explore request/response models.\n\nCloses #337\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(explore): backend /agent/explore/* + queue + budget-decide + KB …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T16:20:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5dc369400ed79f7d203e32a01d2c6f442cd1d8de",
          "body": "The logo was a thin ~188x38 strip, so the tilt was hard to trigger. Move the\ntilt + pointer handlers onto a generously padded wrapper (px-4 py-5) and bump\nthe logo to max-w-204, giving a ~210x76 hover target (was ~188x38) that fires\nthe tilt even above/around the thin logo art.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ui): enlarge the sidebar logo hover zone (#347) (#348)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T16:12:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "62328826e2dbd68f16ed8ebc63db598ca12a526e",
          "body": "- Lower the useTilt defaults (drives all glass cards + the Dashboard hero):\n  maxX 10→7, maxY 13→9, scale 1.045→1.03 — a subtler card tilt.\n- Raise the sidebar logo's tilt: maxX 13→20, maxY 17→26, scale 1.06→1.10,\n  perspective 900→760 — a more pronounced 3D lean.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): soften card tilt, strengthen logo tilt (#345) (#346)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T15:55:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e0460b32ebdfe57ef61d9ae6254a0676bd710ae7",
          "body": "The logo sat on a dark rounded plate that read as a box against the glass\nsidebar. The design floats it transparently, so key out the render's dark\ntextured backdrop and drop the plate.\n\n- Add eme-3d-logo-cut.png: background removed via a border flood-fill\n  (region-growing that follows the wall gra\n[…]\ng with a subtle drop shadow + the existing\n  cursor-tracked tilt — no plate.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ui): float the EMESOFT sidebar logo transparently (#343) (#344)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T15:12:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f37c163de6fc7df79050b6c76bae7f59fbdf7d03",
          "body": "…(#342)\n\nAdd a reusable `useTilt` hook (Framer Motion motion values + spring) that\ntracks the cursor to tilt an element in 3D. The pivot is pinned to the top\nedge (transform-origin 50% 0%, no translate) so a card grows/rotates downward\nand never rises under the header. Honours prefers-reduced-motion\n[…]\ns sidebar), plus an\n  \"AN EMESOFT PRODUCT\" subline to match the design mock.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ui): 3D cursor-tracked tilt hover + EMESOFT sidebar logo (#341) …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T11:34:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e1a3804293340b4768e87b47e0d19d7c71139143",
          "body": "…ssExplorationJob (#338) (#339)\n\nMove the DOM exploration observe→decide→act loop onto the Local Agent\n(paired device), mirroring the agent-driven self-heal path.\n\n- vendor/explore_session.cjs: verbatim copy of the persistent Playwright\n  driver from api/app/services/pw_scripts (require('playwright'\n[…]\nt tests.\n\nGate: npm run build + node --test dist/test both green (40 tests).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(explore): Local Agent exploration loop — vendored driver + proce…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T10:43:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a90ae309ed1edf002c85830a0abd38de8944e779",
          "body": "…eview (#328) (#335)\n\nS5 of the DOM Exploration Agent epic (ADR 0010). Adds a user-triggered\n\"Explore to unblock\" action on a blocked automation case, mirroring the\nSelf-heal flow end to end.\n\n- api.exploreSpec / api.exploreStatus + queryKeys.exploreStatus for the\n  repo-scoped POST /explore + GET /\n[…]\nn typecheck + npm run build green.\nVisual-verified with Playwright chromium.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(explore): frontend Explore-to-unblock + live steps + discovery r…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T09:30:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "96c4ab5abedf55c7e6c144a267be85496977d7e8",
          "body": "…334)\n\nExpose the exploration service over HTTP with the self-heal async\nstart + poll/WS pattern (ADR 0010 §7), so a minutes-long session never\ntrips the ~100s fronting-proxy cap.\n\n- schemas: ExploreTarget/ExploreRequest/ExploreStartOut/ExploreStatusOut\n  + ExplorationResultOut (maps the Exploration\n[…]\ntest_explore_api.py\n(4 passed) with exploration_agent.explore monkeypatched.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(explore): HTTP endpoints for the DOM exploration agent (#327) (#…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T09:07:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f4d6b9f0ab015a82e239388a006af1c54bd0d49e",
          "body": "…s, budget (#326) (#333)\n\nAdd api/app/services/exploration_agent.py: the observe->decide->act ReAct loop\nthat drives the live app (S1 ExplorationObserver), asks Claude one fixed-contract\ndecision per step (skill=automation-generator, decide-prompt builder kept in-file),\nand merges only runtime-obser\n[…]\ntop\ncondition, unreachable=no-write, and the state-changing gate. 10 passed.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "S3: exploration service — action contract, ReAct loop, stop condition…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T08:57:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bbd195a0bd8c30a70421d86cf7e817832e8dbfe5",
          "body": "…ntext (#329) (#332)\n\nrender_project_context now stable-sorts routes and selectors so\nverified_at_runtime entries (confirmed live by the DOM exploration agent,\nADR 0010 §6) render first, each tagged \"✓ runtime-verified\" — selectors also\nsurface the working locator strategy — so downstream generation\n[…]\ne\nentry kind and that it is preferred over source-inferred selectors/routes.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(generation): prefer verified_at_runtime KB entries in project co…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T08:51:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d90d080bc24bdff110bc1f972d2fb7be1f3ef5ad",
          "body": "…action executor (#324) (#331)\n\nS1 of the DOM Exploration Agent (ADR 0010 §1-3). No decide loop, endpoint, or\nKB writes here.\n\n- explore_session.cjs: long-lived Node Playwright process holding ONE\n  chromium browser+page open, line-delimited JSON protocol on stdin/stdout\n  (observe / act / close). o\n[…]\ntion, action mapping, unknown-action rejection,\n  and state-changing gating.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(explore): observation helper + persistent Node browser driver + …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T08:46:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9f6c5ba9872600a1b35ecb918a37f12c9bd0a92d",
          "body": "…ategy, no-clobber (#325) (#330)\n\nAdd merge_verified_discovery() to the KB writer so the DOM Exploration Agent\n(ADR 0010 §5) can record runtime-verified routes/selectors into a project's\nProjectKnowledge row. Mirrors merge_discovered_dom's skeleton: own session,\nper-repo compose_key lookup with proj\n[…]\nrified,\n  preserving its other keys; non-colliding discoveries are appended.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(knowledge): merge_verified_discovery — verified_at_runtime + str…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T08:44:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1aaf1aa1a51b6a9234dc0f5f54f1c55d7e8c5b12",
          "body": "Record the design for the KB-enrichment exploration agent from\nCLIENT-BRIEF-exploration-agent.md and the self-resolved decisions:\npersistent Node Playwright driver, accessibility+DOM observation,\nfixed action contract, mandatory stop conditions (done / step cap /\nrepeat / cost budget), no-clobber ve\n[…]\ngent / Verified-at-runtime / Exploration session\nto the CONTEXT.md glossary.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: ADR 0010 + glossary for the DOM Exploration Agent (#322)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T08:31:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "74c963ff4b2a96f032c8ece725da356a610ac8d7",
          "body": "…ype (#320) (#321)\n\nTwo bugs kept the #318 scroll from firing:\n- Timing: editResult (which bumps the scroll signal) was set in the WS\n  handler, one render before the re-type effect updated editorShown. So the\n  viewer's scroll effect ran against the STALE previous code and found no\n  target line. M\n[…]\nists.\nConfirmed the scroll container is <main overflow-y-auto> in AppLayout.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(automation): actually scroll to the edited line on chat-edit re-t…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-15T06:57:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "43c82821c3ef0b98b44eb962a76b0060f94799f8",
          "body": "…chat-edit re-type (#318) (#319)\n\nWhen Q-Agent applies a chat edit, the editor now:\n- scrolls the first edited line into view (block:center; instant under\n  prefers-reduced-motion), so the user watches the change happen; and\n- highlights the changed lines (reuses CodeHighlight's changedLines green\n \n[…]\nix view mid-animation whose line indices wouldn't\nalign with the final code.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(automation): scroll to first edited line + highlight changes on …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T11:12:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a9ea3fd95660e0792eb59ffd124db95fc26f72fd",
          "body": "…ation (#316) (#317)\n\nTest Data was display-only and never reached spec generation. Now:\n- Fold an editable key/value list (add/edit/remove rows) into the Review\n  Edit mode, saved via the existing PATCH /cases/{id}.\n- Add `test_data` to TestCaseUpdate (schema) — the update handler already\n  applies\n[…]\n) via `_render_test_data`, so\n  generated automation uses QA's exact values.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(review): let QA edit test data and feed it into automation gener…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T10:09:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "588a7af78d40a4b1ce5f6075f9cce1e1968979fc",
          "body": "…y cap (#313) (#315)\n\nIncrement 2 / #313. The agent heal-fix was a synchronous POST that ran a\n~3-min Claude generation on the request thread; behind Cloudflare (100s edge\ntimeout) it returned 524 and the heal failed on attempt 1, even though the\nserver finished the fix.\n\nServer (agent.py):\n- POST /\n[…]\ns: updated postHealFix test to the start+poll flow; added an error-job case.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(heal): make agent heal-fix async (start + poll) to beat 100s prox…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T09:13:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3da459cff0e3703d51b7c40321e9bf1421af1714",
          "body": "…) (#314)\n\nIncrement 1 of #313 (observability). The heal fix generation is the single\nchoke point for both in-process and agent-executed heal, so instrument it:\nlog the live-DOM grounding (element count + path, or \"none\") before the call\nand the fix duration + output size after. Makes \"is heal progr\n[…]\nexceeds\nCloudflare's 100s cap) is tracked in #313 for a follow-up async fix.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(heal): log DOM grounding + fix-gen duration in heal fixer (#313…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T09:05:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7563e02614a690b2cb96af98c2e136c495a1ae1c",
          "body": "…\" (#311) (#312)\n\nA run whose tests passed could show red \"Failed\" because run.status\nconflates pipeline stage/lifecycle with outcome — its \"failed\" only means a\nworker errored/orphaned at some stage (e.g. orphaned at the post-execution\nevidence stage), not that the tests failed.\n\nBackend:\n- RunOut.\n[…]\n0005 orphan recovery + retry still\nkey on them. Presentation + verdict only.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(runs): decouple QA verdict from pipeline status; add \"Incomplete…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T08:46:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d6fe517eb74d3a9db9d8e7a7bab695d6f459260",
          "body": "…(#310)\n\nThe run-context header computed the stage as runStatusToStage[status] ?? 1.\nThat map only covers in-progress statuses, so terminal runs (failed/\ncancelled) always fell back to \"stage 1 of 9\" — a run that failed at, e.g.,\nEvidence misleadingly read as failing at Sync. Fall back to the run's\nfailedStage before defaulting to 1.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(shell): show the real failed stage in the run header pill (#309) …",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T08:27:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0ba860985a64707853825737690ab00447c30ec5",
          "body": "The spec chat content was low-contrast: the assistant message body used the\ndimmer text-ink-soft (#c3c3d0) at 12.5px, and the input field (bg-white/0.03,\nfaint border) barely read as an editable surface.\n\n- Assistant message body -> full-brightness text-ink (#ececf1) at 13px.\n- Input field surface m\n[…]\ne distinct (bg-white/0.07 + stronger border); input\n  text bumped to 13.5px.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(automation): improve chat drawer legibility (#307) (#308)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T08:20:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2287c8f40c451acc7810cda59d05559063b0dd46",
          "body": "… (#305) (#306)\n\nAdds a workspace-level \"Spec quality gate\" toggle (Settings screen, default\nON). When OFF, spec generation / manual edit / chat edit / self-heal fully\nbypass gating — the placeholder/invented-reference/flaky gate, the AI\nautomation-reviewer, and the playwright --list parse check — a\n[…]\noggleRow\n\nTests: new test_generation_gate_disabled_accepts_spec_as_runnable.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(settings): global toggle to enable/disable the spec quality gate…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T08:02:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9dc62dbce094b3ef737ec920a99f42fdbf284b87",
          "body": "The placeholder gate rejected specs whose goto() target is a template\nliteral built from grounded constants — e.g.\n`${BASE_URL}/employers/${EMPLOYER_ID}/groups/${GROUP_ID}`. `_find_invented`\ncompared the raw captured string against concrete KB routes, and\n`_normalize_path` neither stripped `${BASE_U\n[…]\nto verify) are not flagged, honoring the gate's\nno-false-positives contract.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(gate): accept grounded template-literal goto() routes (#303) (#304)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T07:49:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "20b8a0b6967b258969640909b5ee90d5ba043361",
          "body": "…upload (#301) (#302)\n\nThe claim loop is sequential (claimNextJob → processJob → repeat), and\nprocessJob awaited every evidence upload before returning — so while a finished\nrun's (multi-MB) video/trace/DOM uploaded, the agent could not claim a newly\nstarted run, and a stalled upload (fetch had no t\n[…]\n to npx +\ndesktop from the same agent/src. npm publish stays user-run (2FA).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(agent): upload evidence detached so a new run can be claimed mid-…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T07:43:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c96f687451f27311c99bae101217fca0a5f265f7",
          "body": "The editor typewriter re-typed the entire spec from line 1 on every chat\nedit, even for a few-line change. The `automation.chat.reply` payload\nalready carries both `prevCode` and the new `spec.code`, so compute the\ncommon prefix + suffix and animate only the changed middle region — the\nunchanged head/tail stay visible.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(automation): re-type only the changed span of the spec (#299) (#300)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T07:23:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e590efe0b813bb64df7d7b118942eb8e22d15c58",
          "body": "The Local Agent CLI had no way to report which build was running — no\n--version/-v flag and no version in the \"Local Agent started\" banner — which\nmade a support case undiagnosable (a user on the old evidence-before-result\nhang couldn't tell whether their npx build was the fixed 0.1.6 or a stale\ncac\n[…]\nboth channels from\nthe same agent/src; the npm publish stays user-run (2FA).\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): --version flag + version in startup banner (#297) (#298)",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T07:06:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8a668f04ef7df5a60eb2ca36fc1abe20abbb31f5",
          "body": "…296)\n\nIn the Review Center test-case editor:\n- Add a per-row remove button to delete a step.\n- Change the Precondition field from a single-line input to a\n  resizable multi-line textarea.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(review): remove-step control + multi-line Precondition (#295) (#…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T06:44:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3150aeb84f3589d1b26c019788f2147a9f517df2",
          "body": "…l (#293) (#294)\n\nTwo run-processing UX fixes from a run-detail report.\n\n1. Progress events were fire-and-forget with no replay. On a fresh run the\n   pipeline thread publishes the early phase events (Reading → Understanding AC\n   → Business rules → Generating test cases) back-to-back at start, befo\n[…]\nl to the\n   formal \"Generate test cases: {id}\", matching its sibling labels.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(runs): replay last progress event on WS connect + rename gen labe…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T06:36:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3501c89ee260c878caa04c5d39cce77d5a2e9527",
          "body": "…) (#292)\n\nGenerated Playwright specs sometimes emitted a verbose \"Auth note\" block\nreasoning about auth strategy — mocking GET /api/sessions/me, assuming\nVITE_BYPASS_AUTH, fabricating storageState, etc. That is obsolete: auth is\nhandled outside the spec by the saved manual-login session (storageSta\n[…]\nration system prompt). Add tests asserting the policy lands in\nevery prompt.\n\nCo-authored-by: Duna Nguyen <duna.nguyen@emesoft.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(specs): forbid mocked/bypassed auth + 'Auth note' narration (#291…",
          "author_name": "Nguyen Dinh Chuong",
          "author_login": "chuongnd2612",
          "committed_at": "2026-07-14T06:18:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 0,
      "commits_last_year": 315,
      "latest_release_at": null,
      "latest_release_tag": null,
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 4,
      "days_since_latest_release": null,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 14,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@q-agent/agent",
          "exists": true,
          "license": "UNLICENSED",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": false,
          "registry_url": "https://www.npmjs.com/package/@q-agent/agent",
          "is_deprecated": false,
          "latest_version": "0.1.29",
          "repository_url": "https://github.com/chuongduong2810/q-agent",
          "versions_count": 26,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 4037,
          "first_published_at": "2026-07-10T07:00:30.414000Z",
          "latest_published_at": "2026-07-21T11:34:27.311000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 8
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 22
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "agent/tsconfig.json",
        "app/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 68273,
      "source_files_sampled": 347,
      "oversized_source_files": 7,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 8894
    },
    "dependencies": {
      "manifests": [
        "agent/package.json",
        "api/pyproject.toml",
        "app/package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 30,
        "malicious_count": 0,
        "assessed_package": "npm:@q-agent/agent@0.1.29",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm",
        "pypi"
      ],
      "dependencies": [
        {
          "name": "@anthropic-ai/claude-code",
          "manifest": "agent/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.0"
        },
        {
          "name": "@playwright/test",
          "manifest": "agent/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.61.1"
        },
        {
          "name": "commander",
          "manifest": "agent/package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.1.0"
        },
        {
          "name": "electron-updater",
          "manifest": "agent/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.3.9"
        },
        {
          "name": "playwright",
          "manifest": "agent/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.61.1"
        },
        {
          "name": "fastapi",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.115.6"
        },
        {
          "name": "uvicorn",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.34.0"
        },
        {
          "name": "sqlalchemy",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.0.36"
        },
        {
          "name": "pydantic",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.10.4"
        },
        {
          "name": "pydantic-settings",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.7.0"
        },
        {
          "name": "alembic",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.14.0"
        },
        {
          "name": "httpx",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.28.1"
        },
        {
          "name": "loguru",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.7.3"
        },
        {
          "name": "cryptography",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=44.0.0"
        },
        {
          "name": "pillow",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=11.0.0"
        },
        {
          "name": "python-multipart",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.0.20"
        },
        {
          "name": "websockets",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=14.1"
        },
        {
          "name": "argon2-cffi",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=23.1.0"
        },
        {
          "name": "pyjwt",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.10.0"
        },
        {
          "name": "pyotp",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.9.0"
        },
        {
          "name": "psycopg",
          "manifest": "api/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=3.2"
        },
        {
          "name": "@tanstack/react-query",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.101.2"
        },
        {
          "name": "clsx",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "cmdk",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.1"
        },
        {
          "name": "dompurify",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.4.12"
        },
        {
          "name": "framer-motion",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^11.15.0"
        },
        {
          "name": "i18next",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^26.3.6"
        },
        {
          "name": "i18next-browser-languagedetector",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.2.1"
        },
        {
          "name": "lucide-react",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.469.0"
        },
        {
          "name": "qrcode.react",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.2.0"
        },
        {
          "name": "react",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "react-dom",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "react-i18next",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^17.0.9"
        },
        {
          "name": "react-router-dom",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^7.18.1"
        },
        {
          "name": "sonner",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.7.1"
        },
        {
          "name": "tailwind-merge",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.6.0"
        },
        {
          "name": "three",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.171.0"
        },
        {
          "name": "zustand",
          "manifest": "app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.0.2"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 292,
        "open_issues": 22,
        "closed_ratio": 0.877,
        "closed_issues": 157,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "chuongnd2612",
          "commits": 292,
          "avatar_url": "https://avatars.githubusercontent.com/u/56782309?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json",
        "uv.lock"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 30 merged PRs checked by a CI test -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 1,
            "reason": "dependency not pinned by hash detected -- score normalized to 1",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "36 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "cbcb3eefedffcbe9ac76cdc121333a5d5091d6d3",
        "ran_at": "2026-07-29T17:24:41Z",
        "aggregate_score": 1.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-28T07:46:16Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-28T07:46:14Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 96,
          "created_at": "2026-07-09T04:27:05Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 204,
          "created_at": "2026-07-12T16:36:13Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 363,
          "created_at": "2026-07-15T17:40:40Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 419,
          "created_at": "2026-07-20T10:38:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 420,
          "created_at": "2026-07-20T10:39:11Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 421,
          "created_at": "2026-07-20T10:39:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 426,
          "created_at": "2026-07-21T04:43:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 428,
          "created_at": "2026-07-21T06:26:21Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 431,
          "created_at": "2026-07-21T07:08:32Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 436,
          "created_at": "2026-07-21T07:45:06Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 438,
          "created_at": "2026-07-21T08:07:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 440,
          "created_at": "2026-07-21T08:32:23Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 442,
          "created_at": "2026-07-21T08:45:01Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 444,
          "created_at": "2026-07-21T08:55:21Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 446,
          "created_at": "2026-07-21T09:57:37Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 450,
          "created_at": "2026-07-21T10:08:35Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 452,
          "created_at": "2026-07-21T10:16:09Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 454,
          "created_at": "2026-07-21T10:24:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 458,
          "created_at": "2026-07-21T11:20:34Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 460,
          "created_at": "2026-07-21T11:32:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/chuongnd2612/q-agent",
    "host": "github.com",
    "name": "q-agent",
    "owner": "chuongnd2612"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 32,
      "inputs": {
        "security": 29,
        "vitality": 35,
        "community": 12,
        "governance": 41,
        "engineering": 36
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "at_risk",
        "name": "Vitality",
        "value": 35,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 57,
            "inputs": {
              "commits_last_year": 315,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 4
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "4/52 weeks with commits",
                "points": 2.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "315 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 315
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "critical",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "releases_count": 0
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "no releases published",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases_published",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 12,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "critical",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 41,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "merged_prs": 292,
              "open_issues": 22,
              "closed_issues": 157,
              "issue_closed_ratio": 0.877,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "88% of issues closed",
                "points": 41,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 88
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "292/292 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 292,
                      "decided": 292
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 40,
            "inputs": {
              "followers": 0,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "chuongnd2612",
              "public_repos": 23,
              "account_age_days": 2474
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of chuongnd2612",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "chuongnd2612"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "23 public repos, account ~6 yr old",
                "points": 22.1,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 23
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "at_risk",
        "name": "Engineering Quality",
        "value": 36,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "critical",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 24,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "0 out of 30 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 29,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 11,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 14,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 4,
              "scorecard_aggregate": 1.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 30 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 0.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "36 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:@q-agent/agent@0.1.29 runtime dependency closure — what installing the published package pulls in — 30 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@q-agent/agent@0.1.29",
                  "assessed": 30
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 30,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 30,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 65,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 8894
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 54,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json",
                "uv.lock"
              ],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "agent/tsconfig.json",
                "app/tsconfig.json"
              ],
              "agent_commit_share": 1,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "agent/tsconfig.json, app/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "agent/tsconfig.json, app/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "100 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "good",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "primary_language": "HTML",
              "largest_source_bytes": 68273,
              "source_files_sampled": 347,
              "oversized_source_files": 7
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "HTML with type-check config (agent/tsconfig.json, app/tsconfig.json)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "agent/tsconfig.json, app/tsconfig.json",
                      "language": "HTML"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "7/347 source files over 60KB",
                "points": 53.9,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 347,
                      "oversized": 7
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "npm package '@q-agent/agent' points at a different repository (https://github.com/chuongduong2810/q-agent); excluded from ecosystem scoring",
    "Could not fetch pypi package 'q-agent-api' from its registry",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-29T17:24:57.610886Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/chuongnd2612/q-agent.svg",
  "full_name": "chuongnd2612/q-agent",
  "license_state": "absent",
  "license_spdx": null
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计npm.