GitLab setup for WORLDLINE (owner: shafir-01)¶
Included from the repository
This page is docs/GITLAB_SETUP.md from the repository, included as written.
How the project is set up on GitLab.com: protected refs, CI variables, GitLab Duo Agent Platform agents and flows with their triggers, the release flow and Pages. Written against the GitLab 19.x docs; every UI path and version note has its doc URL. Anything marked UNVERIFIED could not be confirmed on an official page or on this project.
Project: https://gitlab.com/shafir2/WorldLine (project id 88121109). The Agent Platform only works in a namespace that is entitled: Premium/Ultimate, GitLab Credits, or a group where Duo Agent Platform is already turned on. Entitlement details are in docs/HACKATHON_REQUIREMENTS.md.
0. Create and push the project¶
# glab auth (once)
glab auth login --hostname gitlab.com
# Create the public project (skip if it already exists)
glab repo create WorldLine --public --description "WORLDLINE: counterfactual computing substrate; branch executions, isolate the causal difference, type the evidence, gate the release." --defaultBranch main
git remote add gitlab https://gitlab.com/shafir2/WorldLine.git
git push -u gitlab main
Verify the MIT license is detected: project home page > About sidebar shows "MIT License". GitLab reads the root LICENSE file.
1. Protect the default branch, the release tags and the kernel paths¶
# Protected branch: only Maintainers push/merge, require CODEOWNERS approval
glab api --method POST projects/88121109/protected_branches -f name=main -f push_access_level=40 -f merge_access_level=40 -f code_owner_approval_required=true
# Protected tags: only Maintainers create v* tags, so only they can cut a sealed release
glab api --method POST projects/88121109/protected_tags -f name="v*" -f create_access_level=40
Then in Settings > Merge requests: set "Merge checks" to require pipeline success, and under Settings > Repository > Protected branches confirm main has "Require approval from code owners" on. CODEOWNERS at the repo root routes invariants/, policies/, worldline/evidence/, .gitlab-ci.yml, .gitlab/duo/, AGENTS.md, CODEOWNERS to @shafir-01. The Duo docs recommend protecting .gitlab/duo/agent-config.yml this way because its setup_script runs with the triggering user's token (https://docs.gitlab.com/user/duo_agent_platform/flows/execution/agent-config-yaml/).
2. CI/CD variables¶
Three variables unlock the protected parts of the pipeline. Set them in Settings > CI/CD > Variables or with glab variable set.
| Variable | Type | What it unlocks |
|---|---|---|
WORLDLINE_KERNEL_KEY |
protected, File | The kernel's Ed25519 private key. kernel-verify seals the evidence bundle with it, which lets authorize reach AUTHORIZED and lets a v* tag become a release. Without it, or on an unprotected ref, kernel-verify fails with "requires a protected ref". |
GCP_PROJECT |
plain | The Google Cloud project id for the manual deploy-gcp job. |
GCP_SA_KEY |
protected, File | JSON key of the deploying service account, with the roles listed in service/README.md. Together with GCP_PROJECT it makes deploy-gcp available on protected refs, where it deploys the public verifier to Cloud Run. |
# Generate the kernel key pair locally; only policies/kernel_public.pem is committed
uv run worldline keygen
glab variable set WORLDLINE_KERNEL_KEY --protected --type file --value "$(Get-Content -Raw policies/kernel_private.pem)"
Remove-Item policies/kernel_private.pem
glab variable set GCP_PROJECT --value "<gcp-project-id>"
glab variable set GCP_SA_KEY --protected --type file --value "$(Get-Content -Raw sa-key.json)"
Protected means only pipelines on protected branches and tags see the variable; the kernel jobs use rules: so they only run there. UNVERIFIED: whether --masked accepts a multi-line PEM on every glab version. The variable is protected and no job prints it, so masking is optional.
Optional, only for the manual duo-repair job (section 7):
# Project access token, scope api, role Developer (Settings > Access tokens)
glab variable set WORLDLINE_DUO_TOKEN --protected --masked --value "<token>"
# Numeric consumer id of the enabled Repair flow, from docs/duo/catalog_ids.json
glab variable set WORLDLINE_REPAIR_FLOW_CONSUMER_ID --value "<id>"
3. Turn on GitLab Duo and the Agent Platform (top-level group Owner only)¶
Skip if the group already has it on. Doc: https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/ and https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/#turn-foundational-flows-on-or-off
- Group > Settings > GitLab Duo > Change configuration.
- GitLab Duo availability: On, or Always on.
- Without Duo Pro or Enterprise seats: GitLab Duo Core: tick "Turn on features for GitLab Duo Core".
- GitLab Duo Agent Platform: tick "Turn on GitLab Duo Agentic Chat, agents, and flows". It is on by default.
- Flow execution: tick "Allow flow execution" and "Allow foundational flows". Leave custom agents and custom flows on.
- Save. Changes can take up to 10 minutes.
Project level (Maintainer): Settings > General > GitLab Duo: turn on GitLab Duo, Allow flow execution, Allow foundational flows. GitLab.com hosted runners work out of the box; flows run in CI jobs tagged gitlab--duo (https://docs.gitlab.com/user/duo_agent_platform/flows/execution/).
Agent configuration file: .gitlab/duo/agent-config.yml is in the repo and is read only from the default branch.
4. Create the agents and flows with scripts/duo_setup.py¶
The three custom agents (WORLDLINE Investigator, Repairer, Skeptic) and the three flows (WORLDLINE Investigate, WORLDLINE Repair, WORLDLINE Skeptic Review) are defined as text in docs/duo/ and published to the project's AI Catalog by one idempotent script. It calls the GraphQL API through your own glab login and stores no token.
uv run python scripts/duo_setup.py --project-id 88121109 --dry-run # show what would be created
uv run python scripts/duo_setup.py --project-id 88121109 # create missing agents and flows, skip existing ones
uv run python scripts/duo_setup.py --project-id 88121109 --update # also push the YAML in docs/duo/flows.md as a new released PATCH version of each flow
uv run python scripts/duo_setup.py --project-id 88121109 --goals # also set per-event trigger Instructions (section 6)
Other flags: --project-path (default shafir2/WorldLine) and --visibility PRIVATE|RESTRICTED|PUBLIC (default PUBLIC). Agents take their system prompt from docs/duo/investigator.md, repairer.md and skeptic.md and their tool list from the script; flows take their YAML from docs/duo/flows.md. The script writes every id it created or found to docs/duo/catalog_ids.json: items, latest versions, the project consumers and their flow triggers.
Manual fallback: create each agent in AI > Agents > New agent with the system prompt and tools from its docs/duo/*.md file, and each flow in AI > Flows > New flow with its YAML block from docs/duo/flows.md.
Docs: https://docs.gitlab.com/user/duo_agent_platform/agents/custom/ and https://docs.gitlab.com/user/duo_agent_platform/flows/custom/.
The script does not enable items. Enable each agent and flow for the project (AI > Agents or AI > Flows > Managed tab > item > Enable > this project) and add the triggers from section 6 in the enable dialog. A rerun of the script then reports each consumer and its triggers.
Test an agent from Chat: open an issue, GitLab Duo sidebar > Add new chat > choose WORLDLINE Skeptic > ask "Review the latest FAIL witness in experiments/out". Chat is useful for checking an agent; the triggers are the automation.
5. Service accounts (automatic)¶
They are not created by hand. Enabling a flow in a group creates ai-<flow>-<group> in the top-level group and adds it to the project as Developer (https://docs.gitlab.com/user/duo_agent_platform/flows/custom/, https://docs.gitlab.com/user/duo_agent_platform/composite_identity/). If main has push rules such as "commit author must be a member", allow the service account (https://docs.gitlab.com/user/duo_agent_platform/troubleshooting/#configure-push-rules-to-allow-a-service-account). Merge requests a flow opens are attributed to the human who triggered the event.
6. Flow triggers¶
Docs: https://docs.gitlab.com/user/duo_agent_platform/triggers/, schema https://docs.gitlab.com/user/duo_agent_platform/flows/custom_flows_schema/ and the flow registry v1 spec https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/main/docs/flow_registry/v1.md
Facts that shape the design:
- A custom flow cannot call a custom agent; it defines its own agents inline in YAML (
AgentComponent+prompts). The flows indocs/duo/flows.mdtherefore embed the Investigator, Repairer and Skeptic system prompts. The custom agents are the Chat-facing versions. - There is no label trigger. Trigger event types are Mention, Assign, Assign reviewer, Pipeline events (experiment), Merge request (Approved / Created / Marked ready / Merge conflict) and Work item (Created / Status changed). The label
worldline:investigateis a human convention for filtering; a work item event or a mention is what fires a flow. - Triggers can only be activated by humans; a flow cannot trigger another flow by mention. The Repairer reaches the Skeptic by opening a merge request.
- For Merge request and Work item events the flow's goal is the bare IID of the triggering resource; for a Mention it is the comment text. The system prompts in
docs/duo/flows.mdtreat a numeric goal as that IID.
Triggers to add when enabling each flow, with their goals:
| Flow | Events | Trigger goal |
|---|---|---|
| WORLDLINE Investigate | Work item; Mention | Read the work item, run the exploration on the scenario it names (default scenarios/port_alert.yaml, seed 42, budget 200), minimise, extract the genome and post one Investigation comment. Do not edit files. |
| WORLDLINE Repair | Mention | Repair the FAIL described in the issue under the AGENTS.md repair contract: make the failing branch PASS, add a regression scenario and test, open one merge request. Never modify invariants/, policies/, worldline/evidence/ or kernel CI jobs. |
| WORLDLINE Skeptic Review | Merge request | Review the merge request against AGENTS.md: boundaries, weakening, reproduced claim, regression scenario, determinism, honesty. Post exactly one note with a PASS or FAIL verdict. Do not approve or merge. |
The exact texts are TRIGGER_GOALS in scripts/duo_setup.py, and --goals writes them to the triggers. Per-trigger Instructions sit behind the feature flag ai_flow_trigger_goals (19.5), which is off on gitlab.com: the server answers Goals are not available, the script reports it without failing, and the system prompts carry the same rule until the flag is on. UNVERIFIED: a Work item > Status changed trigger with a custom status filter such as Investigate, which needs work item custom statuses (Premium/Ultimate, Settings > Issues > Statuses).
Manage triggers later under AI > Triggers (Maintainer) or the flow page > Trigger conditions. Run a flow by hand from Agentic Chat in the project: /flow:worldline-investigate scenarios/port_alert.yaml (https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/).
7. Starting a flow from CI (the duo-repair job)¶
POST /api/v4/ai/duo_workflows/workflows is GA in 19.5 (https://docs.gitlab.com/api/duo_agent_platform_flows/). With ai_catalog_item_consumer_id, goal, project_id and start_workflow: true it starts an enabled catalog flow and returns the run's web_url. .gitlab-ci.yml has a manual duo-repair job that calls it with WORLDLINE_DUO_TOKEN. The token is a project access token with api scope, because the flows' own GITLAB_TOKEN only has ai_workflows scope. If the group has enforce_composite_identity_for_api_started_workflows on, the call returns 403 and a mention is the way to start the flow.
8. Agent run records¶
- Project > AI > Sessions lists every flow run with its status and a Details tab with full or concise logs. Retention is 30 days after last activity (https://docs.gitlab.com/user/duo_agent_platform/sessions/).
- The issue or merge request a flow worked on gets system notes linking the run.
GET /api/v4/ai/duo_workflows/workflows/:id/trace.jsonl(experiment) returns a run's log as JSON Lines. Saved underexperiments/out/duo_sessions/it is agent evidence with produceragent:*and kindEMPIRICALLY_VALIDATEDat best; the kernel never upgrades it.- Group Owners: Settings > GitLab Duo > Change governance > Audit events (beta, storage off by default) gives per-run audit rows and a downloadable JSON record (https://docs.gitlab.com/user/duo_agent_platform/ai-audit-events/). UNVERIFIED on this project's group.
9. Pipeline and releases¶
Stages: test, explore, kernel-verify, authorize, release, pages. The test stage also runs the GitLab SAST, secret detection and dependency scanning templates included from .gitlab/ci/security.yml; findings appear under Secure > Vulnerability report. The manual deploy-gcp job from .gitlab/ci/gcp.yml deploys the public verifier from a protected ref once GCP_PROJECT and GCP_SA_KEY are set.
Release flow: push a tag matching v*. Because the tag is protected, kernel-verify can read WORLDLINE_KERNEL_KEY and seal the bundle, authorize decides for the tagged commit, and the tag-only jobs release-assets and release upload the evidence to the generic package registry and create the release. A DENIED tag never becomes a release. The first release is https://gitlab.com/shafir2/WorldLine/-/releases/v0.1.3-transcend: kernel decision AUTHORIZED, 14 of 14 requirements, with bundle.json, authorization.json, genome.json, minimal_schedule.json, challenge.json and index.json as assets that download without signing in. Cutting a release and verifying one offline: docs/RELEASES.md.
10. GitLab Pages¶
Pages is on by default for public projects on GitLab.com. The pages job publishes public/ from ui/dist plus experiments/out. URL: Deploy > Pages. With "Use unique domain" on, the URL is https://<project>-<hash>.gitlab.io; the Vite build uses base: './' so either works.
11. Order of operations¶
- Push the repository, protect
mainandv*, set the variables (sections 0 to 2). - First pipeline green on
main:test,explore,kernel-verify,authorize,pages. The kernel jobs needpolicies/kernel_public.pemcommitted. - Turn on Duo (section 3), run
scripts/duo_setup.py(section 4), enable the items and add the triggers (section 6). - Open an issue that names a scenario and mention the Investigate service account; the run appears under AI > Sessions.
- Tag a
v*release and verify it offline (section 9).