过去的软件供应链,虽然复杂,但基本有一条清晰链路。
开发者编写代码。
代码进入版本库。
版本库触发构建。
构建系统拉取依赖。
测试通过后生成制品。
制品进入发布流程。
最终部署到生产环境。
这条链路可能包含很多工具,但责任边界相对明确。
某一行代码是谁提交的,可以查 Git。
某一个依赖从哪里来,可以查包管理器。
某一次构建用了什么环境,可以查流水线。
某一个版本何时上线,可以查发布记录。
某次事故由哪个变更引起,可以沿提交历史回溯。
但当 ChatGPT、Codex 以及更复杂的 AI Agent 开始进入软件开发流程之后,传统供应链出现了一个新的变量:
代码不再完全由人直接产生。
它可能由模型生成。
可能由 Agent 修改。
可能经过多个模型协同。
可能根据外部资料、历史代码、测试日志和上下文自动形成。
甚至可能在没有人工逐行编写的情况下,直接进入代码库。
这会带来一个比“AI 写代码准不准”更深的问题:
当代码由 AI 参与生成时,软件供应链如何证明这段代码从哪里来、为什么这样写、经过了什么验证,以及最终由谁负责?
这不是一个单纯的代码质量问题。
它涉及软件供应链治理、构建可追溯性、依赖来源、模型版本、上下文来源、审计记录和责任边界。
AI 编程真正进入工程系统之后,必须回答的不是“能不能生成代码”。
而是:
谁生成的? 基于什么生成的? 用了哪些上下文? 调用了哪些工具? 修改了哪些文件? 经过了哪些验证? 谁批准它进入主分支? 出了问题如何回溯?这些问题共同构成了 AI 时代的软件供应链新边界。
一、传统软件供应链的核心是“来源可识别”
软件供应链并不只是依赖管理。
它包含从源码到制品的完整过程。
可以简化为:
Source Code ↓ Version Control ↓ Dependency Resolution ↓ Build ↓ Test ↓ Package ↓ Sign ↓ Deploy每一层都试图回答一个问题:
当前产物是如何形成的?例如一个容器镜像,可以追溯到:
- 某次 Git 提交;
- 某个构建流水线;
- 某个基础镜像;
- 某组依赖版本;
- 某次测试结果;
- 某个签名证书;
- 某个发布时间。
传统供应链的安全,本质上依赖来源透明。
如果来源不透明,就无法确认制品是否可信。
AI 参与之后,源码层本身变得复杂了。
以前源码主要来自开发者输入。
现在可能来自:
开发者手写 ChatGPT 生成 Codex 自动修改 代码补全工具建议 Agent 根据 issue 生成 Agent 根据测试失败修复 多个 Agent 协商后形成 模型根据外部文档迁移源码不再是单一来源。
它变成了混合来源。
二、AI 代码的“作者”是谁
假设一名开发者向 Codex 输入:
修复订单服务在并发请求下重复扣减库存的问题。
Codex 读取项目代码,生成补丁,运行测试,并修改了四个文件。
最终开发者审查后提交。
那么这段代码的作者是谁?
是开发者。
是 Codex。
是提供训练数据的无数代码作者。
是设计提示词的人。
是审批合并的人。
还是组织这套工作流的系统?
在法律、工程和管理语境里,这些答案可能不同。
从 Git 角度看,提交者可能是开发者。
从生成过程看,主要实现可能来自模型。
从责任角度看,最终批准者仍然是人。
从供应链角度看,最重要的不是争论“谁是真正作者”,而是记录贡献链。
可以设计一种 AI Contribution Record:
fromdataclassesimportdataclassfromtypingimportLiteral ContributorType=Literal["human","model","agent","tool"]@dataclassclassContributionRecord:contributor_type:ContributorType contributor_id:straction:strinput_refs:list[str]output_refs:list[str]timestamp:str例如:
records=[ContributionRecord(contributor_type="human",contributor_id="developer_1024",action="define_task",input_refs=["issue-384"],output_refs=["task-ir-384"],timestamp="2026-07-14T09:00:00Z"),ContributionRecord(contributor_type="model",contributor_id="codex-model-x",action="generate_patch",input_refs=["task-ir-384","context-slice-77"],output_refs=["patch-384-v1"],timestamp="2026-07-14T09:02:00Z"),ContributionRecord(contributor_type="tool",contributor_id="pytest",action="verify_patch",input_refs=["patch-384-v1"],output_refs=["test-report-384"],timestamp="2026-07-14T09:04:00Z"),ContributionRecord(contributor_type="human",contributor_id="reviewer_28",action="approve_patch",input_refs=["patch-384-v1","test-report-384"],output_refs=["merge-approval-384"],timestamp="2026-07-14T09:20:00Z")]这样就不需要用单一作者概念解释复杂协作。
系统记录的是:
谁在什么阶段做了什么。
三、AI 生成代码需要新的 Provenance 模型
Provenance 可以理解为来源、谱系或生成轨迹。
传统代码 Provenance 通常依赖 Git。
Commit ↓ Parent Commit ↓ Author ↓ Timestamp ↓ Diff但 AI 生成代码还需要更多信息。
例如:
模型版本 系统提示 任务描述 上下文文件 检索结果 工具调用 生成参数 中间补丁 测试结果 人工审批可以定义 AI Code Provenance:
@dataclassclassAICodeProvenance:task_id:strmodel_id:strmodel_version:strprompt_hash:strcontext_hashes:list[str]tool_calls:list[str]generated_patch_hash:strverification_report_hash:strhuman_approver:str|None为什么用 hash,而不是把所有内容直接写进提交记录?
因为完整上下文可能很大,也可能包含敏感信息。
Hash 可以证明某份上下文或结果曾经参与生成,但不必公开全部原文。
完整材料可以存放在受控审计系统中。
Git 里只记录引用。
例如提交信息可以包含:
AI-Provenance: prov://task/384 Model: codex-model-x Patch-Hash: sha256:ab34... Verification: verify://report/384 Human-Approved-By: reviewer_28这样未来出问题时,可以从提交追溯到 AI 生成链。
四、Prompt 也属于构建输入
传统构建系统会记录:
源代码版本 编译器版本 依赖版本 环境变量 构建参数AI 编程系统还要增加:
Prompt System Policy Task IR Context Slice Model Version Sampling Configuration Tool Results因为这些信息都会影响输出。
同一段代码上下文,如果 Prompt 不同,生成结果可能完全不同。
同一个 Prompt,如果模型版本不同,结果也可能不同。
同一个模型,如果上下文不同,也可能生成相反方案。
因此,从供应链角度看,Prompt 不是普通聊天内容。
它更像构建参数。
可以把 AI 代码生成抽象成:
Patch = f( Model, Prompt, Context, Policy, Tool Results, Runtime State )传统编译接近确定性过程:
Binary = Compiler(Source, Config)AI 生成通常带有不确定性:
Patch ~ Model(Prompt, Context, Runtime)这意味着仅记录最终 Patch 不够。
还要记录影响生成过程的关键输入。
五、模型版本是新的编译器版本
软件团队通常会固定编译器版本。
因为不同编译器版本可能产生不同结果。
例如:
gcc 12 gcc 13 clang 17AI 编程同样需要重视模型版本。
同一个任务在不同模型版本上,可能出现:
- 不同的架构选择;
- 不同的代码风格;
- 不同的依赖使用;
- 不同的错误处理;
- 不同的安全边界;
- 不同的修改范围。
因此模型版本应该像编译器版本一样被固定和记录。
ai_generation:model:codex-xmodel_version:2026-07-01runtime_version:agent-runtime-3.2policy_version:secure-code-policy-1.8context_builder_version:context-pipeline-2.4如果模型被静默升级,团队可能很难解释:
为什么相同任务突然生成了完全不同的代码?
这就是所谓的模型漂移问题。
六、AI 代码生成具有非确定性
传统构建强调 reproducible build,也就是可复现构建。
相同源码、相同依赖、相同环境,应该生成相同制品。
AI 生成代码却通常不是完全确定的。
即使输入相同,也可能生成不同结果。
patch_1=model.generate(prompt,context)patch_2=model.generate(prompt,context)assertpatch_1==patch_2# 不一定成立这对供应链可复现性构成挑战。
如果无法重新生成同一 Patch,那么未来只能证明“当时生成过”,却无法完全复现生成过程。
可以采用几种策略。
1. 保存最终生成物
这是最低要求。
保存 Patch 保存 Diff 保存测试报告2. 固定生成参数
temperature:0top_p:1seed:438274但即使如此,也不一定跨版本完全复现。
3. 保存模型和运行时版本
Model Version Runtime Version Policy Version Context Builder Version4. 保存上下文指纹
importhashlibdefhash_content(content:bytes)->str:returnhashlib.sha256(content).hexdigest()5. 保存完整决策轨迹
不必保存模型内部推理,但要保存可审计的外部过程:
任务定义 输入文件 工具调用 补丁版本 测试结果 人工反馈 最终决定AI 时代的可复现性,可能不再要求重新生成完全相同结果。
而是要求:
能够证明当时使用了哪些输入、产生了哪些中间结果,以及为什么最终接受该结果。
七、上下文也属于供应链依赖
Codex 修改代码时,不只依赖源码。
它还可能依赖:
- README;
- API 文档;
- issue 描述;
- 代码注释;
- 测试日志;
- 外部技术文档;
- 历史决策;
- 用户反馈;
- Agent 记忆。
这些上下文都会影响结果。
因此它们也是一种依赖。
可以构造 Context Dependency Graph:
Task ├── Source Files ├── API Contract ├── Test Logs ├── Architecture Rules ├── Historical Decision └── External Documentation用程序结构表示:
@dataclassclassContextDependency:dependency_id:strdependency_type:strsource:strversion:str|Nonecontent_hash:strtrust_level:float外部网页和内部接口定义显然不能拥有同样的可信度。
所以 Context Dependency 还要包含信任等级。
TRUST_LEVELS={"current_source_code":1.0,"project_api_contract":0.95,"verified_internal_document":0.9,"historical_issue":0.7,"external_document":0.6,"model_generated_summary":0.4}如果一段代码主要根据低可信上下文生成,就应该触发更严格审查。
八、AI 生成代码可能引入隐性依赖
模型有时会生成看似合理的代码,但引入项目原本没有的技术假设。
例如:
fromfastapi_utils.cbvimportcbv项目里原本并没有fastapi-utils。
或者生成:
importpRetryfrom"p-retry";但依赖文件中没有该包。
还有一种更隐蔽的情况:
模型生成了一个与某开源项目高度相似的实现,却没有明确说明来源。
这些都属于供应链风险。
AI Patch Verifier 应检查:
是否引入新依赖 依赖是否锁定版本 依赖是否有许可证风险 依赖是否真实存在 依赖是否来自可信源 代码是否与已知外部实现高度相似可以加入依赖检查:
classDependencyVerifier:defverify(self,diff,lockfile):findings=[]imported_packages=extract_imports(diff)declared_packages=parse_lockfile(lockfile)forpackageinimported_packages:ifpackagenotindeclared_packages:findings.append({"type":"undeclared_dependency","package":package,"severity":"high"})returnfindings九、测试通过不代表供应链可信
很多团队认为,只要 AI 生成代码通过测试,就可以接受。
这是不够的。
测试验证的是行为的一部分。
供应链可信还需要验证:
来源是否清楚 依赖是否可信 模型版本是否记录 上下文是否可追溯 权限是否合规 许可证是否兼容 人工审批是否存在 生成过程是否可审计例如一段代码可以完全通过测试,但它可能:
- 使用来源不明的实现;
- 引入高风险依赖;
- 复制了受限许可证代码;
- 绕过团队安全策略;
- 由未经授权的 Agent 自动提交;
- 无法说明为什么这样设计。
所以 AI 代码验收要分成多个维度:
Behavior Verification Security Verification Dependency Verification License Verification Provenance Verification Human Approval可以设计一个统一 Gate:
classAICodeSupplyChainGate:defevaluate(self,artifact):checks={"tests":run_tests(artifact),"security":run_security_scan(artifact),"dependencies":verify_dependencies(artifact),"licenses":verify_licenses(artifact),"provenance":verify_provenance(artifact),"approval":verify_human_approval(artifact)}passed=all(result.passedforresultinchecks.values())return{"passed":passed,"checks":checks}十、人工审批不是形式,而是责任锚点
AI 可以参与生成。
AI 可以参与修改。
AI 可以参与测试。
AI 甚至可以参与审查。
但最终仍然需要责任锚点。
所谓责任锚点,就是明确:
谁允许这段代码进入系统?如果没有责任锚点,出了问题后很容易出现:
是模型生成的。 是 Agent 自动改的。 是测试通过了。 是系统自动合并的。但这些都不是责任主体。
因此关键变更必须绑定人工批准。
@dataclassclassHumanApproval:approver_id:strartifact_hash:strapproval_scope:strtimestamp:strcomments:str|None=None审批对象必须是确定的 Artifact Hash。
否则人审批的是旧版本,Agent 后面又改了代码,就会产生审批错位。
defverify_approval(artifact_hash:str,approval:HumanApproval)->bool:returnartifact_hash==approval.artifact_hash十一、AI 生成代码需要类似 SBOM 的清单
传统软件供应链中,SBOM 用于描述软件制品中包含哪些组件。
AI 时代可以扩展出类似概念:
AIBOM,AI Bill of Materials。
它记录某个 AI 生成制品的关键组成。
例如:
artifact:type:code_patchhash:sha256:7af3...generation:model:codex-xmodel_version:2026-07-01runtime:agent-runtime-3.2policy:code-policy-1.8inputs:task_ir:task-384context:-src/order/service.ts-src/order/controller.ts-tests/order_service_test.pytools:-search_code-read_file-apply_patch-pytestverification:unit_tests:passedsecurity_scan:passeddependency_scan:passedapproval:reviewer:reviewer_28timestamp:2026-07-14T09:20:00ZAIBOM 不一定需要记录全部 Prompt 原文。
但应该记录足够的信息,让组织知道这个产物是如何形成的。
十二、AI 编程中的签名机制
为了防止生成记录被篡改,可以对关键记录签名。
例如:
importjsonimporthashlibdefcanonical_json(data:dict)->bytes:returnjson.dumps(data,sort_keys=True,separators=(",",":")).encode("utf-8")defartifact_digest(record:dict)->str:returnhashlib.sha256(canonical_json(record)).hexdigest()AIBOM、Patch 和 Verification Report 可以绑定到同一个摘要链。
Task Hash ↓ Context Hash ↓ Patch Hash ↓ Verification Hash ↓ Approval Signature这类似 Merkle Chain。
只要其中某一部分被修改,后续摘要都会变化。
defchain_hash(previous_hash:str,current_data:dict)->str:payload=previous_hash.encode()+canonical_json(current_data)returnhashlib.sha256(payload).hexdigest()这能提高 AI 生成过程的防篡改能力。
十三、AI Agent 的身份也需要治理
在多 Agent 系统中,不同 Agent 可能拥有不同权限。
Planner Agent Coder Agent Reviewer Agent Security Agent Deployment Agent它们不能共享同一个无限权限身份。
应该为每个 Agent 分配独立身份和最小权限。
@dataclassclassAgentIdentity:agent_id:strrole:strallowed_tools:list[str]allowed_repositories:list[str]max_risk_level:str例如:
coder_agent=AgentIdentity(agent_id="coder-agent-7",role="coder",allowed_tools=["read_file","search_code","apply_patch","run_tests"],allowed_repositories=["order-service"],max_risk_level="medium")Deployment Agent 才能触发部署,但仍需人工审批。
deployment_agent=AgentIdentity(agent_id="deployment-agent-2",role="deployment",allowed_tools=["create_release_candidate","deploy_staging"],allowed_repositories=["order-service"],max_risk_level="high")身份治理是供应链治理的一部分。
因为你不仅要知道“哪个模型生成了代码”,还要知道“哪个 Agent 身份执行了哪一步”。
十四、AI 生成代码的污染传播
如果错误代码进入基础库,它可能传播到大量项目。
这与传统供应链攻击类似。
假设 AI 生成了一个有缺陷的认证中间件。
随后这个中间件被:
- 封装成内部包;
- 复制到多个服务;
- 写进代码模板;
- 被其他 Agent 当作标准实现;
- 进入组织记忆。
那么最初的错误就会持续扩散。
可以表示为:
错误 Patch ↓ 内部公共库 ↓ 项目模板 ↓ 多个服务 ↓ Agent 长期记忆 ↓ 更多生成结果这是一种“认知供应链污染”。
传统恶意代码通过依赖传播。
AI 错误还可能通过记忆、上下文和模板传播。
因此组织应该对以下内容设置更高门槛:
公共代码模板 架构规范 Agent 长期记忆 标准提示协议 共享上下文库 自动生成组件它们一旦错误,影响范围远大于单个 Patch。
十五、AI 时代的 CI/CD 应该扩展成 CI/AI/CD
传统 CI/CD 主要围绕源码构建和发布。
AI 参与后,可以加入新的阶段。
CI Continuous Integration AI AI Generation Governance CD Continuous Delivery完整流程可以设计为:
Task Created ↓ AI Context Built ↓ Patch Generated ↓ Provenance Recorded ↓ AIBOM Generated ↓ Static Analysis ↓ Tests ↓ Dependency Scan ↓ License Scan ↓ Human Review ↓ Artifact Signed ↓ Deploy伪代码:
defci_ai_cd_pipeline(task):context=build_context(task)patch=generate_patch(task=task,context=context)provenance=create_provenance(task=task,context=context,patch=patch)aibom=generate_aibom(patch=patch,provenance=provenance)checks=[lint(patch),type_check(patch),run_tests(patch),security_scan(patch),dependency_scan(patch),license_scan(patch),provenance_check(provenance)]ifnotall(check.passedforcheckinchecks):returnreject_pipeline(checks)approval=request_human_review(patch=patch,aibom=aibom,checks=checks)ifnotapproval.granted:returnreject_pipeline(["human_review_failed"])signed_artifact=sign_artifact(patch=patch,approval=approval,provenance=provenance)returndeploy(signed_artifact)十六、组织真正需要的不是禁止 AI,而是建立边界
面对 AI 生成代码,一种极端方式是完全禁止。
但这会失去效率优势。
另一种极端方式是完全放开。
这会增加供应链风险。
更成熟的方式是分级治理。
低风险代码: 自动生成 + 自动验证 + 人工抽查 中风险代码: AI 生成 + 完整测试 + 人工 Review 高风险代码: AI 可辅助分析,不允许自动提交 核心安全模块: AI 只能提供建议,必须由人工实现或严格复核可以按模块分类:
MODULE_POLICIES={"documentation":"auto_with_check","internal_script":"ai_generate_human_review","business_logic":"strict_review","payment":"human_led","authentication":"human_led","permission":"human_led","data_deletion":"manual_only"}这不是限制工具。
而是根据风险匹配治理强度。
十七、写在最后:AI 代码的价值不只在生成,更在证明它值得进入系统
ChatGPT 与 Codex 正在让代码生成变得越来越快。
但软件工程从来不是一个只追求生成速度的行业。
一段代码真正进入系统之前,必须回答:
它是否正确? 它是否安全? 它是否可维护? 它是否符合约束? 它是否引入新依赖? 它是否能够被审查? 它是否能被追溯? 它是否有人负责?AI 让前四个问题更复杂。
也让后四个问题变得前所未有地重要。
未来的软件供应链,不只管理:
源码 依赖 构建 制品 部署还要管理:
模型 Prompt 上下文 Agent 工具 验证 记忆 人工审批ChatGPT 可以帮助理解需求和组织任务。
Codex 可以帮助生成补丁、运行测试和推进工程变更。
但当它们真正进入软件供应链后,最重要的能力不再只是生成。
而是可追溯性。
能够说明这段代码从哪里来。
能够说明为什么这样写。
能够说明使用了什么模型。
能够说明读取了哪些上下文。
能够说明经过了哪些验证。
能够说明最终由谁批准。
没有这些信息,AI 生成代码只是一个不可解释的产物。
有了这些信息,它才可能成为可信软件供应链的一部分。
所以,AI 编程的下一个竞争点,不只是代码生成率、任务完成率或测试通过率。
而是:
谁能建立一套让 AI 生成代码可证明、可审计、可追溯、可负责的工程体系。
生成解决的是速度。
供应链治理解决的是信任。
速度决定 AI 能做多少事。
信任决定 AI 能进入多重要的系统。
这可能才是 ChatGPT 与 Codex 真正走向企业级软件工程时,必须跨过的一道门槛。