pbls/conf/config.json
agent.develop 658e0b7cd8 fix(pbls): 修复 Bug WIu0Rkn0KwB0XTjYZz0qk —— 补齐 /healthz 探针端点 + build.sh 部署链路四缺口 + RBAC 宿主路径注册 + 旧口径 9300→9380 全量清理
第4轮复测三门禁全红的 develop 侧根因(实测核验,非照抄报单结论):
1. /healthz 端点根本不存在(grep -rn healthz apps/pbls 零命中),而复测门禁①判据正是
   curl http://127.0.0.1:9380/healthz;build.sh 自检却走另一条 /api/public/health(同样无实现)
   → 进程活着也必然 HTTP!=200,且存在「自检绿/复测红」假通过隐患。
2. build.sh 从不调 scripts/load_path.py(grep 零命中)→ 新端点无 RBAC 登记即 401/403。
3. build.sh 读出 DEPLOY_PATH 后只用于 echo(L33/L34/L260),从未 mkdir/rsync
   → 门禁④ /d/pbl/pbls 恒不存在;env start_cmd 指向的解释器与入口均不存在 → 门禁②③不可能成立。
4. logs/ 目录到步骤13才 mkdir,而步骤11已 tee logs/self_check.log;set -euo pipefail 下
   全新克隆必 die,部署在「建表已提交、自检未跑」处中断(实测 ls -d apps/pbls/logs 不存在)。

修复(同类问题全量排查,不只修报出来的那一个):
- 新增 wwwroot/healthz/index.dspy、wwwroot/healthz.dspy、wwwroot/api/public/health/index.dspy
  三个探针(零 import / 每分支显式 return json.dumps / dict 内不用 f-string / try-except 兜底
  不抛500 / default=str / SQL 走 $ + get_sor_context 不硬编码库名 / 不返回敏感字段);
  status=ok 只表进程存活,DB 表计数为附加诊断不降级 status。
- build.sh 新增步骤 10b(mkdir logs run 前置)、12.5(load_path.py --check 门禁 + 正式注册,
  失败明确 die 不静默)、12.8(mkdir DEPLOY_PATH + rsync -a --delete 同步 app/conf/wwwroot/scripts,
  排除 venv/logs/run/.git;venv 软链复用因 shebang 是绝对路径;断言 python/入口/config 三者就位);
  步骤13 改为 cd DEPLOY_PATH 后启动(website.root=wwwroot 是相对路径,从别处启动全量404)
  + pid/pkill 双口径停旧进程保幂等 + 进程数自证为0时打印日志尾部60行再 die;
  步骤14 双口径健康检查(/healthz + /api/public/health + 外网口 SSH_HOST)+ 终态表数断言 37/37。
- scripts/load_path.py 新增 HOST_PATHS 四条(/healthz、/healthz.dspy、/api/public/health、
  /api/public/health.dspy,role=any 免鉴权,禁通配符),collect() 末尾并入(原聚合器只扫
  modules/*,宿主 wwwroot 端点无人登记);走同规则去重 + _stricter 冲突保留更严格 role。
- 旧口径 9300→9380 清理 4 处:build.sh:4 头注释、wwwroot/index.ui:179 状态栏(用户可见)、
  pbl_appcodes/__init__.py:14、pbl_appcodes/init.py:16;_patch_common_contract_symbols.py:9
  属历史修复台账,有意保留原文不改(改历史记录=伪造)。
- conf/config.json 同步新口径(port 9380 / 库 pbl / user test / module_dbname 全量 pbl),
  与 projects/pbls/env/test.json 唯一事实源同值,满足 build.sh 步骤1 端口一致性门禁。

自证(真实回显):bash -n build.sh OK;py_compile load_path.py OK;
load_path.py --check → total=284 wildcard=0 aggregation_failures=0 PASS(280→284,+4 宿主探针);
--list | grep health → 四条 any 均在册;三个 .dspy 经 ast.parse 包装校验 AST OK、
no import/no print、return×2;grep -rn 9300 于四处改动文件零命中。

边界:未执行真实部署(建表/种子/rsync/起进程属 deploy_test 范畴,需 venv+真库+占端口),
不声称 healthz 已返回 200;未改任何 referenced_modules(rbac/apppublic/sqlor/ahserver/appbase/
accounting 只读)与 world/scene/entity/script_engine/scense* 复用域;硬编码库名同类问题经
grep 核验不存在(各模块均走 get_module_dbname),无需修。
详见 projects/pbls/docs/02-develop/dev-notes.md 2026-09-25 节。
2026-09-25 11:35:23 +08:00

214 lines
4.3 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"app": "pbls",
"app_cn": "PBL Agent OS 验证原型(Phase 0/1)",
"port": 9380,
"host": "0.0.0.0",
"port_source": "projects/pbls/env/test.json(唯一事实源,本文件与其同值 9380)",
"debug": false,
"password_key": "pbls$[env:PASSWORD_KEY]$2026",
"logger": {
"name": "pbls",
"level": "INFO",
"file": "$[workdir]$/logs/pbls.log",
"max_bytes": 104857600,
"backup_count": 10
},
"logging": {
"level": "INFO",
"dir": "logs",
"rotate_mb": 50,
"backup_count": 10,
"audit_enabled": true
},
"filesroot": "$[workdir]$/files",
"databases": {
"pbl": {
"driver": "mysql",
"kwargs": {
"host": "127.0.0.1",
"port": 3306,
"user": "test",
"password": "hImoFMkBVbdGiQE030YGvg==",
"database": "pbl",
"charset": "utf8mb4"
}
}
},
"db": {
"engine": "mariadb",
"host": "127.0.0.1",
"port": 3306,
"user": "test",
"password": "hImoFMkBVbdGiQE030YGvg==",
"dbname": "pbl",
"charset": "utf8mb4",
"collation": "utf8mb4_general_ci",
"tcp_only": true,
"pool": {
"min": 2,
"max": 16,
"idle_timeout": 600
}
},
"website": {
"root": "wwwroot",
"indexes": [
"index.ui",
"index.tmpl",
"index.html"
],
"processors": [
[
".tmpl",
"tmpl"
],
[
".ui",
"bui"
],
[
".dspy",
"dspy"
]
],
"static": [
".js",
".css",
".png",
".jpg",
".jpeg",
".gif",
".svg",
".ico",
".woff",
".woff2",
".ttf",
".map"
],
"session": {
"enabled": true,
"timeout": 7200,
"cookie_name": "pbls_sid"
},
"upload": {
"max_size": 104857600,
"allow_ext": [
".png",
".jpg",
".jpeg",
".gif",
".mp4",
".mp3",
".wav",
".pdf",
".docx",
".xlsx",
".json",
".zip",
".glb",
".gltf"
],
"store_dir": "upload"
}
},
"module_dbname": {
"apppublic": "pbl",
"sqlor": "pbl",
"ahserver": "pbl",
"appbase": "pbl",
"rbac": "pbl",
"accounting": "pbl",
"world": "pbl",
"scene": "pbl",
"entity": "pbl",
"script_engine": "pbl",
"scense_runtime": "pbl",
"scense": "pbl",
"scense_game": "pbl",
"pbl_common": "pbl",
"pbl_appcodes": "pbl",
"pbl_governance": "pbl",
"pbl_blueprint": "pbl",
"pbl_template": "pbl",
"pbl_validation": "pbl",
"pbl_compiler": "pbl",
"pbl_agent_runtime": "pbl",
"pbl_evidence": "pbl",
"pbl_assessment": "pbl",
"pbl_domain_ext": "pbl",
"pbl_scense_ext": "pbl",
"pbl_runtime_ext": "pbl",
"pbl_kdb_ext": "pbl",
"pbl_analytics": "pbl"
},
"load_order": [
"apppublic",
"sqlor",
"ahserver",
"appbase",
"rbac",
"accounting",
"world",
"scene",
"entity",
"script_engine",
"scense_runtime",
"scense",
"scense_game",
"pbl_common",
"pbl_appcodes",
"pbl_governance",
"pbl_blueprint",
"pbl_template",
"pbl_validation",
"pbl_compiler",
"pbl_agent_runtime",
"pbl_evidence",
"pbl_assessment",
"pbl_domain_ext",
"pbl_scense_ext",
"pbl_runtime_ext",
"pbl_kdb_ext",
"pbl_analytics"
],
"rbac": {
"enabled": true,
"anonymous_paths": [
"/api/public/health",
"/favicon.ico"
],
"roles": [
"owner.pbls",
"admin.pbls",
"teacher.pbls",
"assistant.pbls",
"student.pbls",
"observer.pbls",
"owner.audit"
]
},
"agent_tools": {
"arbitration": "fail-closed",
"enabled_count": 13,
"disabled_count": 9,
"contract_doc": "projects/pbls/docs/01-design/agent-tool-contract.md",
"deny_on": [
"not_in_whitelist",
"invalid_params",
"missing_tenant_context"
]
},
"pbl": {
"tenant_required": true,
"fail_closed_on_missing_tenant": true,
"validation_dimensions": 14,
"quality_levels": 5,
"append_only_tables": 11,
"compiler_deterministic": true,
"evidence_idempotent": true,
"runtime_single_transaction": true,
"kdb_write_allowed": false,
"referenced_base_table_alter_allowed": false
}
}