Friend 隔离 JIT QA 数据平面:jit-qa-manual-operator 手动运维工作流全解析

发布时间:2026/9/15 11:17:33
Friend 隔离 JIT QA 数据平面:jit-qa-manual-operator 手动运维工作流全解析 Friend 隔离 JIT QA 数据平面jit-qa-manual-operator 手动运维工作流全解析【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend本指南深度解析 Friend 仓库中面向已部署的隔离 JIT QA 平面isolated JIT QA plane的手动运维入口.github/workflows/jit_qa_manual_operator.yml及其配套脚本。该工作流不部署服务、不构建镜像、不调用模型只对命名 Firestore 数据库jit-qa执行有界、可审计、内容无泄漏content-free的运维操作是 QA 数据平面从 Redis API 开通、索引规划、种子注入、双页 drain 验证到回滚/前滚的完整操作手册。读完本文你将掌握该工作流的输入契约、准入校验链、八步操作顺序、索引清单、drain 摘要断言、resume 恢复路径与收据契约并能在仓库源码层面定位每一处实现。工作流定位为什么需要一个隔离的手动运维入口Friend 的 JITJust-In-Time能力依赖一套与共享生产数据平面完全隔离的 Cloud Run 平面。部署侧入口是.github/workflows/jit_qa_cloud_run.yml详见 jit-qa-cloud-run.md它只负责创建/更新命名资源而本工作流是这套已部署平面的操作入口operator entrypoint两者职责严格分离它不部署服务或任务job它不创建 Scheduler 触发器它不构建镜像、不调用模型它不改动任何全局 flag。每一次 dispatch 都必须来自main分支并且必须指名一个带有首次尝试即通过的 Release Eligibility 运行first-attempt Release Eligibility的不可变已部署 QA 源码 SHAimmutable deployed QA source SHA。该 SHA 必须是当前main的祖先ancestor工作流会同时记录已部署源码与操作者当前 main 检出checkout从而保证一个无关的 main 提交不会强制触发 QA 镜像重建。concurrency.group: jit-qa-manual-operator-development且cancel-in-progress: false保证同一时刻只有一个运维运行、且不会被新触发取消。固定的数据平面元组整个隔离平面的所有校验都围绕一组固定常量展开定义于 jit_qa_manual_operator.yml 的env与 jit_qa_cloud_run_contract.py字段值GCP 项目based-hardware-devFirestore 数据库jit-qaFirebase Auth 项目based-hardwareQA UIDvi7SA9ckQCe4ccobWNxlbdcNdC23Cloud Run 区域us-central1drain 任务knowledge-ledger-drain-qa-jobsweep 任务daily-memory-sweep-qa-job网关服务llm-gateway-jit-qaRedis 实例jit-qa-redis运行时服务账号jit-qa-runtimebased-hardware-dev.iam.gserviceaccount.com必需服务 APIredis.googleapis.com在 drain 或回滚之前操作者会读取命名的任务定义并拒绝任何不同的项目、任务名、运行时服务账号、源码标签source-sha、镜像 tag、客户凭据选择器、Firestore 数据库或 UID 白名单。镜像必须是gcr.io开发镜像且以 SHA-256 digest 固定且其source-sha标签必须等于被准入的已部署源码 SHA。输入契约五个 workflow_dispatch 参数工作流通过workflow_dispatch暴露五个输入其中只有operation与source_sha必填输入是否必填说明与约束operation是下拉选择bootstrap、ensure-infrastructure-api、indexes-plan、indexes-apply、prepare、inspect、drain-verify、sweep-verify、rollback、rollforwardsource_sha是不可变已部署 QA 源码 SHA必须是 40 位全小写十六进制且非全零run_id否小写合成夹具命名空间例如qa-proof-20260905除bootstrap/ensure-infrastructure-api/indexes-plan/indexes-apply/sweep-verify外必须提供confirmation否变更性操作的双重确认码见下表resume_execution否仅在drain-verify中有效必须是knowledge-ledger-drain-qa-job-*形式的既有首次执行名确认码confirmation与操作的强制映射在 bashcase语句中逐一校验见 jit_qa_manual_operator.yml 第 111-117 行操作确认码bootstrapPREPARE_QAensure-infrastructure-apiENABLE_QA_APIindexes-plan无只读indexes-applyAPPLY_JIT_QA_INDEXESpreparePREPARE_QAinspect无只读drain-verifyDRAIN_VERIFY_QAsweep-verifySWEEP_VERIFY_QArollforwardROLLFORWARD_QArollbackROLLBACK_QA其余输入级校验包括run_id必须匹配正则^[a-z0-9][a-z0-9_-]{0,47}$resume_execution只能配合drain-verify使用source_sha必须通过git cat-file -e存在于检出仓库且经git merge-base --is-ancestor证明是当前main的祖先。执行前的安全准入链任何操作真正接触云资源之前工作流按顺序完成七道校验全部通过后才继续分支与参数准入GITHUB_REF必须是refs/heads/main随后执行 SHA 格式、run_id 格式、confirmation 匹配、git fetch后source_sha为main祖先等全部校验。Release Eligibility 首次通过证明通过gh api查询仓库中release-eligibility.yml工作流的已完成运行eventpushbranchmainhead_shasource_sha再由.github/scripts/verify_backend_release_admission.py --require-first-attempt校验首次尝试即通过。这保证了被运维的源码本身就是经过发布准入的源码而不是任意提交。检出与 source 记录git checkout --detach main_sha并以omi.jit.qa.operator.source.v1结构写出source.json同时记录deployed_source_sha、current_main_sha、operator_checkout_sha与deployed_source_is_ancestor: True。固定运行时安装以python-version-file: backend/.python-version安装 Python以固定版本astral-sh/setup-uvecd24dd710f2fb0dca1693a67af11fc4a5c5ec84uv0.11.13创建.venv并uv pip sync pylock.runtime.toml安装pinned runtime 环境backend/pylock.runtime.toml。随后依次执行jit_qa_manual_operator.py --help、jit_qa_firestore_index_operator.py --help、jit_qa_sweep_operator.py --help验证三个操作者模块可导入。开发环境认证使用google-github-actions/authv3与development环境的GCP_CREDENTIALS密钥完成认证。Auth action 生成的GOOGLE_APPLICATION_CREDENTIALS文件被保留用于 Firestore ADC 解析工作流校验它确实是 action 的输出路径credentials_file_path且是 service-account 类型、project_id based-hardware-dev、client_email以based-hardware-dev.iam.gserviceaccount.com结尾绝不打印其内容。活动项目校验gcloud config set project后gcloud projects describe确认活动项目就是based-hardware-dev。seed 运行时导入 加密密钥内存加载仅bootstrap/prepare/inspect/drain-verify/rollback/rollforwardSeed 导入被推迟到开发认证之后并从 Secret Manager 读取命名ENCRYPTION_SECRET长度必须 ≥ 32到进程内存中运行jit_qa_seed_and_verify.py --help后立即unset。该密钥永远不会写入收据或工作流产物。需要强调的是运行环境会显式设置隔离选择器OMI_ENV_STAGEdev、GOOGLE_CLOUD_PROJECTbased-hardware-dev、OMI_FIRESTORE_DATA_PLANE_PROJECTbased-hardware-dev、FIRESTORE_DATABASE_IDjit-qa、FIREBASE_AUTH_PROJECT_IDbased-hardware、OMI_JIT_QA_AUTH_ONLYtrue、OMI_JIT_QA_UID_ALLOWLISTQA_UID并同时unset FIRESTORE_EMULATOR_HOST SERVICE_ACCOUNT_JSON FIREBASE_AUTH_CREDENTIALS_PATH——jit_qa_seed_and_verify.py的validate_environment()会对上述任何越界选择器失败关闭fail closed。全新命名数据库的操作顺序对于一个全新的命名数据库文档规定了必须按下述顺序执行的动作ensure-infrastructure-api确认码ENABLE_QA_API仅当部署在 Redis API 开通处停住时运行。检查based-hardware-dev中redis.googleapis.com是否已启用仅在该服务未启用时才启用它。此操作不要求run_id不修改 Redis 实例或任何 Firestore 数据。工作流实现用gcloud services list --enabled --filterconfig.nameredis.googleapis.com探测未启用时执行gcloud services enable并再次探测确认最终产出omi.jit.qa.infrastructure-api.v1收据含state: ENABLED与api_mutation布尔值。indexes-plan检查命名数据库所需的十四个复合索引。若有MISSING继续第 3 步。indexes-apply确认码APPLY_JIT_QA_INDEXES创建缺失索引并等待其 READY。该操作被限制在固定的有界索引集合详见下一节绝不会把生产清单整体套用到 QA 库。bootstrap确认码PREPARE_QA仅创建create-only任何集合已存在时在写入前失败。prepare确认码PREPARE_QA以所选小写合成run_id创建仅 101 行自有合成数据与证据。inspect捕获 pre-drain 的无内容状态content-free。drain-verify确认码DRAIN_VERIFY_QA见双页 drain 验证一节。rollback确认码ROLLBACK_QA仅在经过评审的成功 proof 之后执行。rollforward确认码ROLLFORWARD_QA在 rollback 之后执行。索引集合十四个复合索引 一个 QA 专用单字段索引indexes-plan/indexes-apply的实现位于 jit_qa_firestore_index_operator.py。它以根目录 firestore.indexes.json 为唯一事实来源但只从中选择backend/database/firestore_index_registry.pyINDEX_REQUIREMENTS声明的、与 JIT QA 路径相关的条目而不是整个生产清单。具体包括memory_items.updated_at __name__历史查询conversations.discarded status created_at __name__实体时间线entity-timeline查询两个历史memorieskeyset 查询updated_at DESC __name__ ASC与created_at DESC __name__ ASCconversation_finalization_jobs最老非终态oldest-nonterminal健康查询用于 QA 服务启动期间六条 active-fact 去重查询在 completed-day sweep 应用事实候选时使用subject、slot、entity、entityslot、subjectnormalized-content、entitynormalized-content命名 QA 应用使用的共享聊天查询chat_sessions按plugin_id并以created_at排序messages按plugin_id或chat_session_id并以created_at排序。而旧版chat_sessions文档 ID 回退路径使用 Firestore 的自动同向键索引automatic same-direction key index刻意不作为复合索引目标。此外该操作者还显式维护一个QA 专用、绝不能进生产的单字段 collection-group 索引TARGET_FIELD_INDEXESconversations.status查询作用域COLLECTION_GROUP、升序。由于 Firestore 的 collection-group 单字段配置与仓库的复合索引清单是两套体系代码里用_field_target_state/_apply_field_target通过 Firestore Admin API 单独 PATCHupdateMaskindexConfig并且会沿ancestorField链解析继承配置避免覆盖祖先默认索引。操作者的 stdout 是机器可读收据omi.jit.qa.firestore-index-plan.v1/omi.jit.qa.firestore-index-apply.v1共享 reconciler 的进度日志被重定向到 stderr。bootstrap 与 prepare合成夹具的创建边界bootstrap与prepare都实现在 jit_qa_seed_and_verify.py其命令行形式为python3 backend/scripts/jit_qa_seed_and_verify.py bootstrap python3 backend/scripts/jit_qa_seed_and_verify.py \ --run-id qa-proof-20260905 prepare python3 backend/scripts/jit_qa_seed_and_verify.py \ --run-id qa-proof-20260905 inspectbootstrap 只允许空用户平面_assert_named_database_empty()使用collections()元数据清单证明数据库为空。唯一被容忍的例外是后端启动可能遗留的conversation_recovery_state/byok_abandonment_sweep恢复游标——但仅当它恰好包含generation≥1 整数、resume_after_pathnull与updated_at带时区且不超未来 5 分钟三个字段时才被保留并计算其 SHA-256 元数据摘要。任何其他集合、文档、字段或畸形值都会在写入前失败关闭。bootstrap 只创建固定 QA UID 的最小users/{uid}profile、testers/{uid}测试标记并调用ensure_canonical_apply_control_state创建真实的writer_modecompatibility的 apply-control 围栏fence。它绝不伪造 ledger completion 或 cutover 收据——cutover 权威唯一属于 drain 任务的publish_ledger_migration_cutover路径。jit_qa_bootstrap/{uid}持久标记使重试幂等同时拒绝任何非自有或畸形文档。prepare 创建 101 条 canonicalmemory_items行及其 101 份合成证据。行通过run_id命名空间隔离jitqa-run-id-legacy-000…-100并刻意省略ledger_schema_version——它们是生产 drain 迁移预算每运行 100 行设计来补齐的 legacy 形态 fixture。标记omi.jit.qa.seed-and-verify.v1同时存在于顶层字段与类型化promotion字段中以便 canonical 迁移通过model_dump()重写后标记仍能存活支撑 cutover 后的无内容排他性证明。所有写入都是 create-only已存在且带自有标记的文档被视为已存在幂等带外来标记的文档是硬失败。双页 drain 验证100 1 稳定重试drain-verify是整个工作流最核心的验证动作实现在 jit_qa_manual_operator.py 与 jit_qa_seed_and_verify.py 的verify_bounded_progress()。其执行模型为校验已部署的不可变任务先以gcr.io/based-hardware-dev/knowledge-ledger-drain-qa-job:source_sha解析镜像 tag用gcloud container images describe解析出sha256:digest再gcloud run jobs describe取出线上任务定义交给validate-jobvalidate_job_resource()校验任务名、jit-qatrue与source-sha标签、镜像必须等于解析出的 digest、环境字面量、Secret 绑定与运行时服务账号完全一致。执行三次first / second / retry通过 Cloud Runexecution override启动——gcloud run jobs execute --async --update-env-vars KNOWLEDGE_LEDGER_DRAIN_ENABLEDtrue,KNOWLEDGE_LEDGER_DRAIN_UID_ALLOWLISTQA_UID。--async是为了避开 launcher 请求 deadline随后用execution-state轮询status.conditions[typeCompleted]最多 150 次 × 10 秒。解析聚合日志行每次执行后用日志过滤器resource.typecloud_run_job AND resource.labels.job_nameknowledge-ledger-drain-qa-job AND labels.run.googleapis.com/execution_nameexecution读取日志用正则SUMMARY_RE提取恰好一行聚合摘要knowledge_ledger_drain: scanned.. inventoried.. attempted.. allowlist_blocked.. blocked.. revoked.. remaining.. cutover.. migrated_rows.. errors..按相位断言精确计数器SUMMARY_EXPECTATIONS即真实生产 drain 的100 行/运行迁移预算语义相位inventoriedscannedattemptedremainingcutovermigrated_rowsfirst11110100second111011retry稳定重试010000任何errors非空、任何计数器不匹配都会拒绝该相位。 5.持久任务闸门复查每次执行结束后再次run jobs describevalidate-job确认持久化任务的环境覆盖没有把KNOWLEDGE_LEDGER_DRAIN_ENABLED闸门留在打开状态它必须始终为false。 6.seed 操作者的真实持久化验证以三次摘要调用jit_qa_seed_and_verify.py verify要求101 行/101 证据全部保留、legacy_rows0且ledger_rows101、writer_modeledger、fenced completion 存在、prompt projection 扫描全部 101 行、全局 drain 游标未被写入。 7.持久化围栏durable proof检查用curl读取三个 Firestore 文档——users/uid/memory_state/apply_control、users/uid/memory_control/knowledge_ledger_migration、users/uid/memory_control/knowledge_ledger_prompt_projection——并由durable子命令validate_durable_state()断言apply-control 的writer_modeledger、completion 的schema_versionknowledge_ledger.v1且statuscomplete且blocking_row_count0、projection 的schema_versionknowledge_ledger_prompt_projection.v1且statuscomplete、三者head_commit_id/writer_epoch/account_generation/source_generation围栏相互匹配、projection 的legacy_row_count0、blocking_row_count0且scanned_row_count1。resume_executionlauncher 超时后的恢复路径如果首次 launcher 在其客户端请求超时之后返回了一个执行--async只是避免请求 deadline不保证快速返回可以把该确切的knowledge-ledger-drain-qa-job-*名称作为resume_execution传入且必须在执行后的 24 小时内。恢复路径会重新读取并校验该执行的源码标签、不可变镜像、服务账号、QA 身份/数据库、已启用的 drain override——validate_execution_payload()会逐一比对完整环境字面量集合与ENCRYPTION_SECRET、POSTHOG_PROJECT_API_KEY两个 Secret 绑定任何差异都拒绝日志新鲜度从 1h 放宽到 24h要求首页计数器与自有的 101 行夹具/控制状态之后才启动第二页恢复路径会执行jit_qa_seed_and_verify.py inspect并断言retained_rows101、retained_evidence101、legacy_rows1、ledger_rows100、missing_rows[]、writer_modecompatibility、completion_presentfalse、cursor_presentfalse。rollback 与 rollforward写者控制平面的显式往返rollback只在经过评审的成功 proof 之后执行调用canonical 写者迁移回滚助手rollback_ledger_writer_to_compatibility定义于 utils/memory/knowledge_ledger_migration.pyjit_qa_seed_and_verify.py的rollback_fixture()使用python3 backend/scripts/jit_qa_seed_and_verify.py \ --run-id qa-proof-20260905 rollback \ --confirmation ROLLBACK_QA它不重写任何行、证据或内容只把写者从ledger模式切回compatibility模式然后inspect校验writer_modecompatibility且 101 行/101 证据全部保留、元数据摘要metadata_digest与回滚前完全一致。rollforward紧随 rollback 之后通过工作流执行一次有界 retryrun_drain rollforward对应SUMMARY_EXPECTATIONS[rollforward]migrated_rows0、cutover_users1随后同样读取三个 Firestore 文档做durable校验断言 canonical ledger 围栏已恢复writer_modeledger、completion/projection 均为complete且围栏一致。收据契约内容无泄漏content-free原则drain-verify的收据将精确执行名、聚合生产者计数器、seed 验证器结果以及Firestore completion / prompt-projection 围栏联结在一起但不含任何行内容或 provider 载荷。上传的工作流产物仅限于无内容的 operator 收据schemaomi.jit.qa.manual.operator.v1statusPASS含source_sha、run_id、project、database、uid、source块与各阶段执行名/摘要/seed 验证/durable proof原始 Cloud Run 描述、日志、Firestore 文档和临时启动文件全部留在产物暂存目录之外并在步骤结束时被清理rm -f。sweep-verify的收据额外包含model_calls: bounded_by_QA_override_policy与scheduler_mutation: False明确声明没有调度器变更。文档特别强调成功的模拟器证明emulator proof是代码契约结果不能替代命名的 Cloud Run 执行及其真实 rollout/准入路径本地正确性验证请使用firebase emulators:exec --only firestore --project demo-omi-jit-qa PYTHONPATHbackend python3 backend/scripts/jit_qa_seed_and_verify_emulator_test.py见 jit_qa_seed_and_verify_emulator_test.py该测试注入且明确标注了唯一的 rollout 决策边界。收据应与独立的隔离平面就绪收据一起保留——后者由 jit_qa_receipt.py 产出omi.jit.qa.cloud.v1就绪候选reviewed: false需 root 操作者人工复核后提升为激活收据证明的是端点/依赖元组两者组合才构成完整的证据链。失败处理与运维注意事项若任何前置条件失败正确做法是保留失败的收据修复命名的 QA 资源或数据平面状态后再重试绝不把操作者指向共享开发任务shared development job。文档与工作流实现共同强调的边界还包括每次 dispatch 只允许在main分支上运行且source_sha必须通过首次尝试的 Release Eligibility 准入所有变更性操作都需要匹配的 confirmation 码confirmation 不匹配会立即exit 1sweep-verify使用独立命名空间qa-sweep-github_run_id-attempt经OMI_JIT_QA_SWEEP_ADMISSIONtrue显式准入且模型/成本预算被严格限制如MEMORY_DAILY_MEMORY_SWEEP_MAX_MODEL_CANDIDATES1、MAX_MODEL_COST_USD0.05、gpt-5.6-luna的 12 288 input / 256 output token 卡片预算并读取llm_gateway_attempts的持久化记账行作为成本权威见 jit_qa_sweep_operator.py本地功能回退是scripts/dev-harness/jit_qa_local_stack.py但同样不是隔离云伴生/网关/Redis/真实 Firebase 身份路径正在服务的证据。相关文档与代码导航部署侧平面说明jit-qa-cloud-run.md命名资源、OMI_JIT_QA_AUTH_ONLY应用围栏、jit-qa-redis与 Secret 绑定、run_oncetrue的 drain 一次执行语义seed/验证操作者文档jit-qa-seed-and-verify.mdCLI 用法、收据契约、模拟器边界收据 schema 与就绪候选jit_qa_receipt.py云资源契约环境/Secret 白名单、镜像 digest 约束jit_qa_cloud_run_contract.py复合索引注册表与全局清单firestore_index_registry.py、firestore.indexes.json固定运行时依赖backend/pylock.runtime.toml这套手动运维工作流本质上是一份可执行的安全契约把隔离 QA 平面的全部常量、准入规则与断言固化为代码任何越界都以失败收场从而让一次真实的 ledger 迁移100 1 稳定重试既可以在命名 QA 数据库中反复验证又绝不会波及共享生产数据平面。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询