Commit Graph
303 Commits
Author SHA1 Message Date
Autumn-27 9e98407528 fix(assets): 企业归属重算不再被单行非法 ip 打挂,并明确告知是哪些资产
assets.ip 是自由文本(Agent 的 insert_assets 和资产 API 都可能写进主机名),
而 db/companies.go 的 IP/CIDR 归属匹配裸转 a.ip::inet。只要表里有一行不是
合法 IP,PostgreSQL 就抛 22P02 中断整条语句,连带同事务的新增/修改企业资产
范围、删除企业全部失败回滚。这个裸转从项目初始化提交就存在。

- schema.sql 新增 try_inet(text):非法值返回 NULL 而不是抛错。没用
  pg_input_is_valid 是因为那要 PG16+,这里要兼容更老的存量库。
- 四处 IP/CIDR 匹配统一改用 try_inet。原先 task_scope.go 和
  task_assets_context.go 用的正则 a.ip !~ '[^0-9a-fA-F:.]' 只检查字符集,
  abc.def 这类全 hex 字母的主机名照样漏过去后炸,一并换掉。
- 跳过不能是静默的:重算会统计并抽样列出这些资产(id + 取值),说明它们不会
  被网段规则归属。信息通过企业范围接口新增的 warnings 字段返回并在前端以
  长停留 toast 展示,同时无条件写入服务端日志,覆盖没有前端响应的路径
  (删除企业、scopesentry 同步、Agent 写入)。
- warnings 与 errors 分开:errors 仍只表示本次提交里不合法的行,既有数据
  问题不该被记到用户这次输入头上。

验证: 干净库上 go test -p 1 ./... 仅剩 1 个既有失败(TestCompanyScopeInvalid,
与本改动无关,stash 后同样失败);改动前在含真实数据的库上有 14 个失败,现已
全部通过。go build / vet / gofmt / tsc / biome 均通过。
2026-08-24 10:16:17 -04:00
Autumn-27 fea78b2d6f feat(tasks): 任务列表支持批量修改分类
勾选多个任务后可一次性移动到目标分类,或选「未分类」把它们移出当前分类。

- db: 新增 SetTasksCategory,在单个事务里校验分类存在性并 UPDATE ... WHERE
  id=ANY(...),返回真正被更新的 id 和刷新后的分类(含 task_count)。分类检查
  放在事务内,避免并发删除把 UPDATE 变成外键冲突。单批上限 100。
- server: 新增 POST /api/tasks/category/batch。写入原子,响应里的逐任务失败
  只可能是勾选后又被删掉的任务;顺带把 category_id 的解析(必填但可为 null)
  抽成 parseCategoryIDField 与单任务接口共用。
- server: 把批量 id 的 trim/归一/去重逻辑从 controlTasksBatch 抽成
  normalizeBatchTaskIDs,两个批量端点共用同一套重复判定。
- manager: SetTasksCategory 在 taskStateMu 内完成 DB 写入与运行中任务 DTO
  刷新,防止与单任务更新交错后留下过期的 category_name。
- web: 选中工具栏新增「修改分类」对话框(需确认目标,避免误点批量改动);
  「未分类」哨兵值统一提取为 UNCATEGORIZED_VALUE。

验证: go build / vet / gofmt、db 与 server 新增测试连本地 PG 实跑通过、
tsc --noEmit、biome check、next build 均通过。
2026-08-24 09:16:44 -04:00
Autumn-27 3eca390089 style(db): 对齐 ICP 范围匹配 SQL 缩进,并注明手工挂载资产的语句顺序依赖
#53 引入 icp 范围匹配时,三处覆盖度 CTE 里新增的 OR 分支混进了 tab 缩进,
与同一 JOIN 条件内其它分支(纯空格)不一致。统一改回空格,SQL 语义未变
(git diff -w 无差异)。

AttachAssetsToTask 里 UPDATE assets 会先触发 trg_assets_task_links 写入
source='system',随后的显式 INSERT 才把来源改成 'manual'。加注释说明这层
顺序依赖,避免后续调换两条语句导致人工挂载的来源静默退化成 system。
2026-08-24 08:55:55 -04:00
Autumn-27 6b44a94ec7 Merge pull request #53 from neouks/main
feat: 同步 0.3.3 并增强任务、资产与 LLM 运行时

冲突解决说明:
main 此前已合入同源分支(#42/#31)的大部分内容,与本 PR 形成大量重复历史,
git 报出 18 个文件 104 处冲突。逐块核对后确认 PR 树已完整包含 main 的全部
内容(net diff 无任何纯删除,adc8e35/476a445/9fad543/9d8e0ba 等 main 侧修复
均已在内),故统一取 PR 侧。

另修正 db/assets.go 的静默错误自动合并: git 未报冲突但把 CountByTask /
CountsByTypeForTask / DeleteByTaskID 等 166 行重复插入两遍,会导致方法重复
定义编译失败。

相对 main 的净新增功能:
- 任务分类: task_categories 表 + tasks.category_id,分类增删改查与筛选,
  改名时同步刷新运行中任务的 DTO
- 任务测试资产: task_asset_links 表记录关联来源(agent/manual/api/task/
  anchor/system/legacy),支持实时挂载与移出;移出仅解绑,保留全局资产
- 测试范围新增 icp / keyword 两种 kind,ICP 按去空格小写匹配 icp/app_icp
- Worker 会话标题旁展示当前测试资产及来源摘要,继承任务仅暴露终态意图
- 前端抽出公共 ScopeTextEditor,补齐上述接口的 mock 契约

验证: go build / go vet / go test / tsc --noEmit 均通过。
2026-08-24 08:36:34 -04:00
pphua 43cd6b072c docs: align changelog with implemented features 2026-08-24 19:59:55 +08:00
pphua ec971c63d2 feat(api): integrate task workflows and mock contracts 2026-08-24 19:31:16 +08:00
pphua ef57f3f196 fix(ui): harden pagination and selection controls 2026-08-24 19:31:09 +08:00
pphua 32d872ed9c fix(ui): normalize displayed version label 2026-08-24 19:30:55 +08:00
pphua 5863c12886 feat(tasks): enhance detail sessions and runtime status 2026-08-24 19:30:44 +08:00
pphua af3149901e feat(ui): add traffic and tool detail drawers 2026-08-24 19:30:35 +08:00
pphua fd2ddbc9d7 feat(skills): track usage and missing dependencies 2026-08-24 19:30:14 +08:00
pphua 8dca38c4b9 feat(metrics): add persistent LLM usage analytics 2026-08-24 19:30:07 +08:00
pphua 04fda4cd01 feat(tasks): add categories templates and batch controls 2026-08-24 19:29:46 +08:00
pphua 3bedbdc669 feat(chat): add conversation pinning and rename controls 2026-08-24 19:29:38 +08:00
pphua 27dc6d8bad feat(findings): group findings and add deepen workflows 2026-08-24 19:29:24 +08:00
pphua 31dc9e7446 feat(assets): add editable company and task scopes 2026-08-24 19:29:14 +08:00
pphua 4392b4fee1 feat(tasks): add runtime controls and inherited context 2026-08-24 19:29:00 +08:00
pphua 18926c129f feat(llm): add profile failover and pool health 2026-08-24 19:28:18 +08:00
pphua d4b21f0bdb build: improve release packaging and updater 2026-08-24 19:27:39 +08:00
pphua 58f23a2773 同步 2026-08-24 14:14:15 +08:00
Autumn-27 9ab9fe2327 docs(changelog): 定版 0.3.3(补齐 v0.3.2 之后的新增/修改/修复) 2026-08-23 13:32:44 -04:00
Autumn 734c7b21cf Merge pull request #49 from Autumn-27/fix/prompt-var-duplicate-now
fix(prompt-vars): 消除变量目录与全局变量撞名导致的前端 key 重复
2026-08-24 01:16:29 +08:00
Autumn-27 9fad543168 fix(prompt-vars): 消除变量目录里与全局变量撞名导致的前端 key 重复
goals 内置 agent 的变量目录里定义了 Now,seed 进 agent_prompt_vars 后,
withGlobalVars 又追加了同名的全局 runtime 变量,getAgent 返回两条 Now →
前端 variables.map 的 key={v.name} 重复,React 报错并可能丢/重渲子节点。

- withGlobalVars: 追加全局变量前剔除同名的库内条目,全局(权威 runtime 定义)
  胜出,保证返回列表名字唯一。对所有现存库立即生效,无需迁移。
- db.go: 从 goals 内置目录删掉冗余的 Now(已是全局变量);扩展既有清理 DELETE
  一并清掉旧库残留的 'Now' 行(已发版→DB 改动带迁移)。
- 新增 withGlobalVars 去重回归测试。

go build / go vet / go test ./server 全绿。
2026-08-23 13:14:28 -04:00
Autumn 1de7a383cc Merge pull request #48 from Autumn-27/fix/llm-precommit-safe-retry
fix(llm): 提交前安全窗口内对同一 provider 重试,减少 model_error
2026-08-24 01:06:00 +08:00
Autumn-27 9d8e0ba988 fix(llm): 提交前安全窗口内对同一 provider 重试,减少 model_error
SDK 的 doStream 只重试建连阶段(拿到 200 之前);流一旦开始,中途断流 /
overloaded / 流内 429 等瞬时故障会直接冒泡成 model_error,零重试。表现为
worker 常出现「无总结,终态 model_error」,甚至只跑了一两个工具就中断。

在 streamTaskLLM(所有任务 agent 的统一出口)里补一层同 provider 退避重试:
- 仅在 committed 之前(还没向调用方交付任何输出)触发,重放相同请求不会
  重复模型输出或工具副作用,绝对安全
- 最多 2 次,退避 0.5s→1s(封顶 4s),ctx 取消立即让位
- 只重试瞬时故障(传输 reset/EOF/timeout、408/429/5xx、流内 overloaded);
  额度耗尽交给 profile 故障转移、上下文过长交给 harness reactive 压缩、
  4xx 确定性拒绝一律不重试
- 给不上时原样落到既有透传/故障转移逻辑,行为不变

新增 3 个回归测试(重试到成功 / 重试耗尽如实上报 / 4xx 不重试),退避以
变量暴露便于测试置零。go test -race 全绿。
2026-08-23 13:02:54 -04:00
Autumn 5574624984 Merge pull request #47 from Autumn-27/fix/capture-usage-yield
fix(test): capture_usage 遵守迭代器协议,消除 yield 告警
2026-08-24 00:53:38 +08:00
Autumn-27 5f39391594 fix(test): capture_usage 遵守迭代器协议,yield 返回 false 即停止
消除 vet 的 "yield may be called again after returning false" 告警:
每次 yield 后判断返回值,false 则 return,不再继续调用 yield。
2026-08-23 12:52:32 -04:00
Autumn 2a07893f64 Merge pull request #46 from Autumn-27/feat/operation-constraints
feat(constraints): 操作约束(抽取→注入 planner/worker 提示→总览管理)
2026-08-24 00:49:09 +08:00
Autumn-27 27c3248844 feat(constraints): 操作约束抽取→注入 planner/worker 提示→总览管理
- 新表 task_constraints(allow/deny),CREATE TABLE IF NOT EXISTS 无需迁移
- 新工具 set_constraints:目标拆解器 round-0 先抽约束再拆目标、主 agent 运行时可补;
  拆解器提示词要求约束自包含(把「当前目标」等指代替换成具体域名/端口)
- constraintBlock 按最高优先级注入 planner+worker 系统提示;去偏:多样性/拓面显式服从约束
- 注入范围可配置(constraints_inject_planner/worker,默认都开,每轮读、即时生效)
- 总览「约束管理」卡片 + CRUD 接口(增删改不通知 planner,下轮规划自然读到)
- goals 提示词把抽约束步并入可编辑正文;旧库经 flag 守卫的一次性 reseed 追加新默认版本
2026-08-23 12:48:01 -04:00
Autumn d8f34cc79d Merge pull request #45 from Autumn-27/feat/goal-management
feat(goals): 总览目标管理(增/删/改) + 通知 planner 并复活任务
2026-08-23 23:42:43 +08:00
Autumn-27 d28ecd67fe feat(goals): 总览新增目标管理(增/删/改),同步通知 planner 并复活任务
- 总览页新增「目标管理」卡片,支持人工查看/新增/修改/删除目标
- 新增/修改:通知 planner(新增了目标/由 old 变为 new)并复活任务
- 删除:硬删除 goal 节点(级联删边/锚点),通知 planner,不复活任务
- 无 schema 变更:目标仍存 exploration_nodes(kind='goal'),仅加查询方法
2026-08-23 11:41:53 -04:00
Autumn-27 025e1ce445 feat(intents): 删除 work 改为「停止+记录原因」,不再销毁数据
删除不再删意图与其产出,而是:停到 stopped、要求填写删除原因、把原因作为
事实挂到该意图上、并写进意图 payload,规划者收到 cancelled 触发(意图内容+原因)。

- db: StopIntentWithReason —— 标 stopped + 建原因事实 + 连边 + 合并 payload
  (cancelled_by_user/cancel_reason),单事务;旧 CancelIntent 保留不再被调用
- agent/server: renderTriggers 加 cancelled 分支;Task.NotifyCancelled;
  controlIntent/applyIntentControl 接收并要求 reason
- web: 删除弹窗改为必填原因的 Textarea;列表用红色垃圾桶+删除线+「已删除」徽标
  区分;选中会话顶部横幅展示删除原因;controlIntent 传 reason

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 11:14:04 -04:00
Autumn-27 3297ca1821 change(llm): 出站代理留空=直连,不再回退 HTTP_PROXY 环境变量
- quotaAwareHTTPClient: proxy 为空时 transport.Proxy=nil(直连),
  不再用 http.ProxyFromEnvironment 吃 HTTP_PROXY/HTTPS_PROXY
- 前端代理输入:提示可带账号密码(socks5://user:pass@host:port),
  文案改为「留空表示不使用代理(直连)」

显式的 ARTEX_LLM_PROXY 环境变量不受影响(仍写入 Config.Proxy)。

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:41:16 -04:00
Autumn-27 52aba07846 feat(mainagent): 默认给主 agent 加上 steer_work 工具
主 agent 之前只能 add_hint/add_intent,无法对已在运行的 work 实时纠偏。
现将 planner 的 steer_work(不打断、不丢进展地注入纠偏指令)默认下放给主 agent。

- MainAgentTools 加入 steerWorkTool
- MainAgent 加 steerWork 字段与 SetSteerWork,Chat 里接进 ToolSet
- 全局与 per-task router 两处主 agent 构建均 SetSteerWork(engine.SteerWork)
- 主 agent 提示词「操舵」段补充 steer_work 用法引导(仅影响新 seed)

作用域安全:steer_work 仍校验 intent_id 属于本任务(关联任务只读)。

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:37:24 -04:00
Autumn-27 052cf63338 fix(intercept): 加固裁判输出解析,避免正确 DENY 被当成放行
模型若照抄提示词里的中文标签(如「拦截:DENY:...」),旧解析要求关键词在行首,
会判为无法解析 → 按 fail_action(默认 allow)兜底,导致真实拦截被放行。

- ParseVerdict 改为扫描行内最早出现的 ALLOW/ASK/DENY 关键词,容忍前缀标签
- 提示词输出段改用箭头并明确禁止输出中文标签,附合法输出示例
- 新增 prompt_test.go 覆盖标签回显、全角冒号、大小写、超长理由截断等场景

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:05:10 -04:00
Autumn-27 95d2309935 feat(intercept): 未命中规则的命令接入 LLM 兜底审批
在正则/字符串规则之外新增一套独立的模型兜底层:规则命中直接按规则走;
一条规则都没命中时,才由模型做语义判定(ALLOW/ASK/DENY),人工审批兜底。

- intercept: DefaultJudgePrompt(三态判定提示词)+ ParseVerdict;Reviewer 回调注入;
  Judge() 读全局 llm_judge_* 配置、超时/失败回退、ask 填审批超时、模型判定加 [模型] 前缀
- guard: applyIntercept 未命中分支调 Judge;模型 allow 不落库,deny/ask 带 reason 入库
- db: intercept_pending 加 reason 列(带 ALTER IF NOT EXISTS 补旧库);
  create 函数支持 reason 与 ruleID 0→NULL;历史查询带出 reason
- server: 用 providerForProfile + 单次 Stream 收集注入裁判;GET/PUT /api/intercept/judge
- web: 拦截页拆「拦截规则 / 模型配置」两 tab;拦截范围提为共用信息条;
  模型配置双栏布局(提示词直接展开编辑);审批/任务拦截页标注「模型判定」+ 理由

配置默认值:失败回退 allow、审批超时动作 deny、模型 allow 不落库、
提示词默认即内置模板(清空回退模板)。无需 DB 结构性迁移(judge 走 settings KV)。

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 10:02:43 -04:00
Autumn-27 f63a451b87 feat(tasks): 任务增加可选名称字段
tasks 表新增 name 列(空=未命名,前端回退到描述),端到端打通:
- DB: schema.sql 加列并补旧库 ALTER;tasks.go 的 Task/CreateOptions/CRUD;
  findings.go 分组与任务下拉带出 t.name
- 后端: TaskDTO、内存 Task、createTaskReq 透传 name
- 前端: 类型/API/mock 加 name;任务列表新增名称列与搜索、创建表单加名称输入;
  详情页与漏洞页标题回退 name || description

Claude-Session: https://claude.ai/code/session_019QXSCDmzimwnjntBNCgUD7
2026-08-23 09:08:05 -04:00
Autumn-27 070784d43c revert: 恢复版本号动态注入,本地构建回退为 dev
本地运行不再硬编码 0.3.3,改回 dev;build.sh 通过 git describe
注入真实 tag 并经 ldflags 覆盖 main.version。

Claude-Session: https://claude.ai/code/session_01HMRoSjvobCcuH5gbKkStFF
2026-08-23 03:55:10 -04:00
Autumn-27 ca1d22b227 docs(insert_assets): 明确 related 判定,CDN/静态资源类应设 false
补充工具描述:与任务无关的资产(如仅存静态资源的 CDN)必须设
related=false 或不插入,避免污染资产覆盖度分母。

Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 12:33:26 -04:00
Autumn-27 a3fe9b767b feat(ui): 系统设置接入会话发送键位与 Web 搜索代理
- 会话发送键位改用 chat-send-mode 统一配置(CHAT_SEND_MODE_OPTIONS/
  useChatSendMode),替换页面内自维护的模式常量。
- Web 搜索区新增代理输入框(http/socks5,留空为直连)。

Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 11:46:12 -04:00
Autumn be90d520a3 Merge pull request #43 from Autumn-27/feat/traffic-sqlite-store
feat(traffic): 正文入库 + 全文搜索,删除改为 SQL 事务
2026-08-22 23:43:55 +08:00
Autumn-27 fb666c03cc feat(traffic): 正文入库 + 全文搜索,删除改为 SQL 事务
流量录制不再镜像 URL 路径写文件树,改为整条 exchange 落 SQLite:

- record: 元数据/头/正文写库;>256KB 的 body 才溢出到 _blobs(单层
  桶、按 hash 去重),库里留 8KB 预览 + 指针。文本正文全量喂 trigram
  FTS 索引(二进制按 content-type 跳过),支持任意子串与中文全文搜索。
- 删除退化为一个 SQL 事务级联删四张表,host 树后台异步回收,不再在
  写锁内 RemoveAll + 全树扫描——删除从数小时降到毫秒级,期间不再停摆录制。
- gcBlobs 改走 blob_refs 反查,顺带清理空桶目录;保留对旧文件树的
  引用扫描与 Get 回落,历史数据免迁移仍可读、可搜(元数据)、可删。
- 新增 traffic_blob 工具与 GET /api/traffic/blob 流式下载大 body;
  traffic_search 增加 body_contains 全文参数。

新表均为 CREATE TABLE IF NOT EXISTS,旧库自动补建,无需 ALTER 迁移。

Claude-Session: https://claude.ai/code/session_01RtPQYJ8W1mcaace3sHWGDm
2026-08-22 11:36:58 -04:00
Autumn-27 22ae280584 feat(insert_assets): 资产可标记是否与当前任务相关(related)
insert_assets 每条资产新增 related 入参(默认 true):仅在任务开启资产
覆盖度功能时生效——true 才自动纳入覆盖度(测试范围分母),false 则只入
共享资产库、不计入本任务覆盖度(如顺带发现的旁站/无关资产)。

- Call 内部按 related + coverageDisabled 双重 gate 决定是否 AddAutoScope
- 覆盖度关闭时 related 无意义,经 StripCoverageParams 从最终工具 schema
  剔除(必须在 ToolResolve 的 DB schema 覆盖之后做,故在装配链末端处理)
- 旧库经 refreshBuiltinToolSchemas(flag v6) 刷新 insert_assets schema,
  否则首插入only 的 seed 收不到新参数
- 补 StripCoverageParams 回归测试(开启保留/关闭隐藏/不改原始 schema)

Claude-Session: https://claude.ai/code/session_01Jm87Gr5fq5aso6SfLyguhx
2026-08-22 10:26:11 -04:00
Autumn-27 eb3f278711 feat(task): 资产覆盖度功能可按任务开关
创建任务时新增「资产覆盖度功能」开关(默认开)。关闭后:
- 不计算/展示测试覆盖度,总览卡片隐藏、覆盖度 API 返回 enabled:false
- 态势图仅展示资产不显示测试进度(B1:抹平 tested、去已测统计与图例)
- 不再自动累积 task_scope(source=auto)
- planner/mainagent 的 add_task_scope、list_untested_assets 从工具列表剔除
- graph_overview 丢弃 coverage 度量块、保留 scope 字段(防上下文污染)

company 关联(task_scope kind=company)与此开关无关,永不受影响:
insertTaskCompanies 不 gate,TaskCompanyIDs 照常读回,scope 字段照常喂给 agent。

DB:tasks 加 coverage_enabled 列(schema.sql + ALTER ADD COLUMN IF NOT EXISTS
补旧库,默认 true 保持存量任务原行为)。

Claude-Session: https://claude.ai/code/session_01Jm87Gr5fq5aso6SfLyguhx
2026-08-22 10:03:18 -04:00
Autumn-27 5126ac4592 feat(ui): 会话输入框发送键位可配置
0.3.2 把 Ctrl+Enter 发送改成了 Enter 发送,习惯旧键位的用户没有退路。
系统设置新增「会话输入框发送键位」,两种模式二选一:

- Enter 发送,Shift+Enter 换行(默认,即 0.3.2 现行为)
- Ctrl+Enter 发送,Enter 换行(0.3.2 之前的键位)

实现:

- 新增 lib/chat-send-mode.ts,复用已有的 local-storage.client 读写封装;
  纯前端偏好,不入库、不随账号同步
- 对话页与任务详情主 Agent 会话原本各自内联了一份相同判断,统一收敛到
  shouldSubmitOnKey(),加模式时不必两处各改一遍
- enter 模式保留原判断(只排除 Shift),没顺手把 Ctrl+Enter 也变成换行——
  原本它是会发送的,改掉会让没动设置的用户感到意外
- 中文输入法保护照旧:isComposing / keyCode 229 时放行,回车选词不误发送
- useSyncExternalStore + 自维护订阅集合:storage 事件只在其他标签页触发,
  本页改完需手动 emit 才能立即生效;getServerSnapshot 给默认值避免 SSR 不一致
- ctrl-enter 模式同时接受 Ctrl 与 Cmd(macOS)

按需求放在系统设置页,未采用 issue 中建议的输入框内控件。

Closes #39

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 07:18:21 -04:00
Autumn-27 ca7300ad52 feat(ui): 任务列表操作列增加详情与暂停/继续按钮
操作列此前只有删除,暂停/继续必须先勾选再点批量控制,进详情页只能点标题。

- 详情按钮用 Button asChild 包 Link,渲染为真正的 <a>,中键新开标签、
  右键复制链接都可用
- 暂停/继续按钮按状态自动切换形态,调已有的 controlTask 接口,无需改后端;
  终态任务渲染为 disabled 而非隐藏,各行操作列宽度才不会随状态跳动
- 状态门控与后端 applyTaskControlWithCause 对齐:非终态且未暂停可暂停
  (即 created/queued/running),paused 可继续,不会给出后端会拒绝的动作
- 控制后清空 lastRef 再 load:列表轮询按负载去重,不清会把状态回写挡掉,
  看起来像点了没反应;放在 finally 里是因为失败多为状态已变化,更需要重拉
- 批量控制原本自己写了一遍状态列表,改为与行内按钮共用 taskControlAction(),
  避免将来新增状态时两边判断分歧

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:51:39 -04:00
Autumn-27 76c648d36d fix(ui): 任务总览的测试范围显示企业名称而非 ID
/api/tasks/{id}/scope 只返回 company_id,前端无从解析名称,测试范围里的
企业行只能渲染成 "company #4"。

- TaskScope 增加 company_name,ListTaskScope 与 ListTaskScopeWithSources
  都 LEFT JOIN companies 带出名称(LEFT 而非 INNER:域名/IP/网段行的
  company_id 为 NULL,内连接会把它们全过滤掉)
- 两个查询函数都改,避免结构体字段"一个填一个不填"的不一致
- 前端优先显示名称,公司被删后的残留行仍以「企业 #N」兜底

覆盖图谱的企业节点本就查名显示(task_scope.go 的 BuildCoverageGraph),
不受影响。

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:43:08 -04:00
Autumn-27 f0c2b43802 Merge PR #42: 0.3.3 Worker/LLM/Agent/UI 增强
来自 @neouks 的 PR #42,外加本地的三个后续修改:

- fix(llm): Agent 绑定优先于任务 LLM 配置链
- feat(ui): 会话徽标改显示 LLM 配置名
- fix(scope): 含点号的文本不再被误判为 ICP 备案号

已知遗留(code review 确认,评估影响可控,后续单独处理):
- db/exploration.go CancelIntent 先数后删的并发竞态,会回滚并向用户报
  "intent cleanup changed concurrently",不损坏数据
- db/assets.go company_source 优先级 CASE 在 8 处手写重复,改动易漏
- server/goals.go reconcileConcurrency 第二个 if 是死代码

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:26:43 -04:00
Autumn-27 fbddf1cfb5 fix(scope): 含点号的文本不再被误判为 ICP 备案号
单文本框自动分类只要文本里出现 "icp" 或 "备案" 子串就判定为 ICP 规则。
备案号本身不含点号(京ICP备12345678号-1),而 ICP 归属走的是精确相等比较
(companies.go 的 kind='icp' 归属查询),所以掺了域名或版本号的描述性文字
一旦被判成 ICP,就会存成一条永远匹配不上任何资产的死规则,且无任何提示。

分类条件增加"不含点号",半角 . 之外一并覆盖全角 .和中文句号 。——粘贴
中文内容时容易出现这两个,真实备案号里同样不会有。

已有的 "京 ICP备 123号"、"沪网备案 9988" 仍判定为 ICP,不受影响。

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:26:07 -04:00
Autumn-27 9b75afe9f1 feat(ui): 会话徽标改显示 LLM 配置名
会话标题右侧的徽标原本显示模型 ID,改为显示配置名称;模型 ID 移到 hover
的 tooltip 里,并去掉其中的协议名(openai/anthropic 等)。

- 抽出 resolutionLabel(),徽标、aria-label、tooltip 共用一处取名逻辑;
  environment 来源的配置可能没有 name,按 name → model → 未命名配置 降级,
  避免渲染出空徽标
- 去掉 font-mono:等宽字体是为模型 ID 准备的,配置名多为中文
- tooltip 用 filter(Boolean).join(" / ") 拼接,模型名缺失时不留孤立斜杠

Claude-Session: https://claude.ai/code/session_01Q8nhYZfS4H8fsSCBJXxbSy
2026-08-22 06:18:07 -04:00