How a project profile works
A profile connects your project to the pipeline engine: where to work, how to prepare the environment, which checks to run and how to deliver the result.
Configure a profile with an agent
Open a chat with your project as its working directory and copy the prompt below. Use it for a new profile or an existing one: the agent will inspect the project, check available runners and configure the profile using your answers.
Verification and acceptance recommendations are collected in a separate guide.
Configure this project's profile for GrigDesk pipelines.
Read the documentation for this installed GrigDesk version: project setup, the profile contract and the standard pipeline-sample. Find the actual profile directory and check whether this project already has a profile. Preserve existing settings.
Read the recommendations for profiles and routes: /docs/projects/recommendations/. Apply them to environment checks, review and audit instructions, acceptance evidence and rework transitions. In your final report, explain how they apply to this project and what remains unverified.
Inspect the repositories, stack and project rules. Identify build and relevant test commands, environment preparation and how to verify the result. Propose isolated or shared mode, the routes we need, allowed commands and delivery. Ask me about anything you cannot determine from the code and settings.
Find out which runners this installation supports and which are ready to use: check adapters, required CLIs or the built-in runtime, authentication status and model catalogs. An adapter list alone does not prove readiness. For a source installation, use engine/bin/factory runners; for a ready-made bundle, find the equivalent command in the installed version's documentation. Show the available options and propose a primary runner, optional fallbacks, models and supported reasoning effort for route roles. Ask about my preferences for speed, quality and cost. If authentication or dependencies are missing, explain what needs preparing.
Create or update a local profile; for a new one, use pipeline-sample if it fits. Configure repositories, the environment, checks and editor commands. Change runners and models through the standard CLI using the current settings revision. Validate the configuration and related routes, then check host readiness without sending model tasks. Agree on a real trial run with me separately.
Finish by showing the files and settings, selected runners and models, check results and remaining steps. Keep secrets and keys out of the report and the project repository.Start with connecting a project. The reference below covers reading and manual setup: environments, runners and models and readiness checks. Examples use a sample backend and frontend project. Commands on this page never run automatically.
Profile, route, node and attempt
| Concept | Responsibility |
|---|---|
| Profile | Project repositories, environment, boundaries, checks, runners and available routes. |
| Route | Stages, instructions, transitions, rework and human decisions. |
| Node | An agent, a trusted command, a human gate or a displayed status. |
| Attempt | One task execution with a pinned route revision and environment contract. |
One profile can serve multiple repositories and routes. The Projects section stores the project record; creating that record does not configure an executable profile.
Profile files
profiles/<name>/
profile.sh
runners.env
graph.json
dashboard.env
routes/
editor-capabilities.json
...
up.sh / down.sh / status.sh
...| File | Purpose |
|---|---|
profile.sh | Trusted project variables and functions: code, environment, boundaries, commands and delivery. |
runners.env | Primary and fallback runners, model families, versions and reasoning effort. |
graph.json | Profile capabilities, including the route-v2 protocol. |
dashboard.env | Dashboard settings: repository paths, container names and timer command. |
routes/ | With script-based authoring: route source, instructions and a publication script. With editor-based authoring, the draft is the source. |
routes/editor-capabilities.json | Profile commands and additional context sections available to the editor. |
up.sh, down.sh, status.sh | Project scripts for preparing, removing and inspecting an isolated sandbox when needed. |
| Test wrappers and helpers | Stack-specific commands for tests, data checks and environment preparation. Their names belong to the project. |
The four root files form the launch profile. Its contents are local configuration, not automatically supplied with the engine. The profiles directory may be a link to the installation's data directory.
Storage settings
| Setting | Purpose |
|---|---|
FACTORY_PROFILES_DIR | Explicit profile directory; the engine requires an absolute physical path without symlink components. |
GRIGDESK_ROUTES_DIR | Published route store; defaults to ~/.factory/routes. |
GRIGDESK_ROUTES_AUTHORING_DIR | Editor drafts; defaults to the published store path with .authoring appended. |
GRIGDESK_FACTORY_PROFILE | Server's default profile; does not create or configure it. |
Source files in the profile's routes/ directory and published revisions are separate. Editing an instruction file alone does not change the route used by a new launch.
What happens at launch
- Triage reads source repositories, project information and product rules.
- Policy suggests a route based on task kind and depth; the human makes the final choice.
- The engine pins the selected route and environment contract in an attempt.
- The profile prepares an isolated sandbox or checks the existing shared environment.
- At each node the engine invokes an agent, runs a trusted command or waits for a decision.
- If the route includes delivery, its final node performs the permitted actions.
Environment, workflow and model selection are separate settings. Changing a review model, for example, does not require changing route transitions.
profile.sh: context and triage
This is executable Bash. Loading it must not start a preview or perform preparation: the server also reads it during task assessment and when opening launch forms.
| Setting | Purpose |
|---|---|
PROFILE_NAME | Profile ID matching its directory name. |
PROFILE_CTX | Stack and project information for triage. |
PROFILE_AGENT_CWD | Base directory for profile consumers. Route execution uses the first repository's workspace. |
PROFILE_AGENT_DIRS | Additional space-separated paths. Route execution derives access from pinned workspaces. |
PROFILE_SERVICE_HOST | Host or address without scheme or port; defaults to 127.0.0.1. Set localhost if the application treats them differently. |
PROFILE_TRIAGE_REPOS | Space-separated key:/absolute/source pairs for triage repositories. |
PROFILE_TRIAGE_MARKERS | Project risk signals such as tenant migrations, charges or access changes; inputs to task assessment. |
PROFILE_TRIAGE_RULES | key:relative/file product-rule pairs; keys must be declared among triage repositories. |
PROFILE_TRIAGE_ROUTES | kind:depth=routeId mappings such as feature:light=small; the target must exist in the catalog. |
PROFILE_LOOP_MAX_ROUNDS | Handoff limit in loop mode: 1–300, default 20. Does not affect ordinary routes. |
PROFILE_CTX helps assess the task. Execution agents receive mandatory rules separately through profile_project_context(): JSON with stack and guardrails arrays.
Functions called by the engine
These functions are hooks. They normally return data on stdout, diagnostics on stderr and a nonzero exit code for failure.
| Hook | Result or action |
|---|---|
profile_workspace_mode() | Explicitly selects isolated or shared. |
profile_repositories(TASK) | Returns name<TAB>source<TAB>workspace rows; the first repository sets the main working directory. |
profile_project_context() | Returns the stack and boundaries pinned in the attempt. |
profile_source_branch(TASK, REPO) | Returns the task workspace branch; its creation base is configured separately. |
profile_container(TASK) | Returns the preview or container name without starting it. |
profile_stand_alive(TASK) | Checks readiness of the existing preview without creating or removing resources. |
profile_route_command(...) | Maps an allowed commandId to trusted code and returns a JSON verdict; required for command nodes. |
profile_delivery_targets(TASK) | Defines target branches per repository for routes containing ship. |
profile_delivery_actions(TASK) | Adds permitted delivery actions; task-comment is a supported example. |
profile_slots() | Reports the slot range and occupancy without reserving a slot. |
TASK is the task number; REPO is the repository name. The first six hooks are mandatory for an executable profile. Conditional requirements and exact signatures are in the profile contract.
The profile defines what profile_stand_alive checks. A successful health check does not replace verification of the user scenario.
Task environment
| Property | isolated | shared |
|---|---|---|
| Code | Separate task worktrees. | Existing working copies. |
| Preparation | Profile up.sh TASK and readiness check. | Check an existing prepared environment. |
| Resources | Defined and allocated by the profile. | The profile declares resources; a lease protects them until completion or abandonment, including human gates. |
| Removal | Only resources belonging to the task. | The external environment is not removed. |
Shared mode additionally requires profile_service_ports, profile_exclusive_resources and profile_instrumentation_restored. See the shared working copy limit.
A backend and frontend sandbox can create two worktrees, two containers and separate data schemas while sharing MySQL, ClickHouse and Redis servers. isolated does not promise a separate virtual machine or a dedicated database server.
The task number typically determines resource and branch names. A free slot index determines ports and other limited resources. They are different values. Port formulas, datasets, database schemas and test login settings belong to project scripts.
The profile must prepare a consistent test environment. Copy dependencies without shared inodes so one task's cache writes cannot change another task's dependencies. The generated t<TASK>.env is lifecycle output, not a file for manually reconfiguring an active attempt.
Check environment readiness
Configure checks for the processes, connections and user scenario required by the task, as well as HTTP availability. Read the environment readiness recommendations.
The commands below check configuration and host readiness. Configure application behavior checks separately in the profile and route.
From a source GrigDesk installation, replace <name> with your profile name:
engine/bin/factory-check <name> --quickAfter runner setup and authentication, check the host:
RUN_HOST_PREFLIGHT=1 engine/bin/factory-check <name> --host-preflightThese checks do not send a task to a model. For a ready-made bundle, use the check commands documented by your installed version; real tasks are run separately.
Permissions, checks and time
| Setting or hook | Purpose |
|---|---|
PROFILE_AGENT_ALLOW, PROFILE_AGENT_DENY | Additional command permission and denial arrays. An allow does not override a deny. |
profile_stage_agent_allow(RUN_KEY) | Role-specific permissions; publication commands can be limited to SHIP. |
profile_stage_result_check(TASK, RUN_KEY) | Early result validation while the agent can still correct it. |
profile_route_node_evidence_check(...) | Trusted evidence validation after the runner finishes. |
profile_route_volatile_paths(TASK) | Allowed untracked check artifacts; Git-tracked files remain protected. |
profile_timeout_class(CLASS) | Overrides a node class timeout in seconds. |
Engine defaults: planning, standard, review, delivery, check — 30 minutes; test, build — 60; diagnostic, browser — 90. A profile can increase planning to an hour, for example. Inspect the actual class: a REVIEW node need not use review.
A “check within 15 minutes” instruction and a process timeout are separate limits. budgetClass alone does not impose a token or spending limit.
Command nodes are useful for deterministic checks. For example, VERIFY runs tests and static checks, REVIEW examines code and may be allowed limited fixes, and RECHECK checks those fixes. Command nodes do not select a model even if runners.env retains settings for a role with the same name.
runners.env: runners and models
This file contains KEY=VALUE pairs without export, quotes or shell substitutions. Change it through factory profile … runner/model …: writes are atomic and revision checks protect concurrent edits.
| Key | Purpose |
|---|---|
RUNNERS_SCHEMA | Format version, currently 1. |
CONFIG_REVISION | Runner settings revision, not the route revision. |
RUNNERS_COVERAGE=required | Requires compatibility checks against host runners. |
PROJECT_RUNNER_PRIMARY | Project's primary runner. |
PROJECT_RUNNER_FAILOVER | Ordered, comma-separated fallbacks; empty means none. |
STAGE_<RUN_KEY>_PRIMARY | Primary runner for a role such as BUILD or REVIEW. |
STAGE_<RUN_KEY>_FAILOVER | Role-specific fallbacks. When stage primary is set, missing fallbacks do not inherit the project's chain. |
MODEL_DEFAULT_<PROVIDER>_* | Default model fields for that provider. |
MODEL_<RUN_KEY>_<PROVIDER>_* | Role-specific model field overrides. |
RUNNER_<PROVIDER>_AUTH_PROFILE | Optional account-context label, not a password or credential file path. |
Runner priority: task node → whole task → profile role → project. An override replaces the entire primary/fallback pair. Model family and effort are resolved separately.
Model fields
| Suffix | Meaning |
|---|---|
FAMILY | Family from the runner's catalog. |
VERSION | Version within the family; latest selects a compatible stable model. |
VARIANT | Model variant; auto uses the default variant. |
EFFORT | Reasoning level supported by the chosen runner and model. |
EXACT | Exact model ID, taking precedence over family, version and variant search. |
FAMILY_FAILOVER | Another family from the same provider for a corresponding limit. |
Each field inherits independently: nonempty role value → that provider's DEFAULT. latest does not permanently pin one model ID. Provider fallbacks and a fallback family within one provider are separate mechanisms.
Example settings fragment:
STAGE_BUILD_PRIMARY=codex
STAGE_BUILD_FAILOVER=glm
MODEL_DEFAULT_CODEX_EFFORT=high
MODEL_BUILD_CODEX_EFFORT=xhighBUILD uses Codex with GLM as fallback. Codex effort for this role is xhigh; other unspecified roles inherit high. Other keys select family and version from installed runner catalogs. This fragment is not a complete profile.
With STAGE_AUDIT_PRIMARY=glm and no stage failover, AUDIT has no fallback even if the project's default fallback is Codex. A product check failure alone does not mean the task should be repeated with another model.
For CLI examples and host checks, see runner configuration.
Route and node fields
| Field | Controls |
|---|---|
bootstrap | Separate scouting: required or skip. Skipping does not skip environment preparation. |
entry, sequence.main, sequence.tail | Entry point, main order and delivery tail. Transitions must still be explicit. |
executor | Node type: agent, command, gate or status. |
runKey | Role used to select a runner and model; routes do not contain provider, model or effort. |
commandId | Trusted profile command ID, not an arbitrary shell string. |
prompt.blocks, prompt.requiredContext | Instruction blocks and required context sections. |
policy.filesystem | state-only: no code edits; workspace-write: code changes; transactional-write: controlled temporary instrumentation. |
policy.browser | Independent browser permission: default forbid or allow. |
policy.timeoutClass, policy.budgetClass | Timeout class and budget class label. |
fanout | Multiple executors within a node, their maximum and whether sequential execution is allowed. Parallel mode requires an agent with state-only. |
retry.noResult | Retries without an accepted result. |
retry.productFailure | Retries of this node after a product failure. |
retry.providerFailure | Retry count and strategy for provider failures. |
on | Outcome transitions: next, rewind, stop or permitted escalation. |
onFailure | Transitions by failure owner: build, tests, plan, environment, human. |
Agent and command outcomes are done, skipped, failed, exhausted; gates use approved and rejected. A rewind resets the continuous segment from its destination through the current node. Retrying a node and returning to its author are different actions; positive retry.productFailure conflicts with rework on failed. Command nodes have zero retries.
Example: four routes in one project
A backend and frontend application can use this progression. These names and stages are a project configuration example, not mandatory GrigDesk presets.
| Route | Sequence |
|---|---|
small | BUILD → VERIFY → REVIEW → RECHECK → BROWSER → human acceptance → SHIP. |
feature | PLAN → SKEPTIC → plan approval → TESTS → BUILD → VERIFY → BROWSER → AUDIT → human acceptance → SHIP. |
fix | REPRO → DIAGNOSE → BUILD → VERIFY → REVIEW → RECHECK → BROWSER → human acceptance → SHIP. |
debug | REPRO → INSTRUMENT → DIAGNOSE → HYPOSKEPTIC → PROOF → TRANSLATOR → cause approval → TESTS → BUILD → VERIFY → REVIEW → RECHECK → MEASURE → BROWSER → human acceptance → SHIP. |
small has no separate plan but still covers the entire task. feature adds a plan, critique, approval and tests before implementation. fix starts by reproducing a defect. debug requires proof of the cause before fixing it and measurement afterwards.
A matching triage map:
PROFILE_TRIAGE_ROUTES="feature:light=small feature:mid=small feature:full=feature
debug:light=fix debug:mid=fix debug:full=debug"All four can use bootstrap: skip, assigning the task map to the first agent. Browser acceptance can be mandatory: skipped stops for a human. In feature, VERIFY can check a frozen TESTS snapshot; shorter routes can run tests from the diff. The profile and published route define these rules.
Runner assignments also belong to the project. For example, Codex can plan, diagnose and implement while GLM critiques, reviews and audits. Overrides and fallback can change the runner, so the default policy alone does not guarantee different providers for author and reviewer.
Dashboard and delivery
dashboard.env controls project display, not model assignment:
| Setting | Purpose |
|---|---|
FACTORY_BE_ROOT, FACTORY_FE_ROOT | Repository roots for the dashboard; do not replace profile_repositories. |
FACTORY_MYSQL_CONTAINER, FACTORY_REDIS_CONTAINER | Data containers for diagnostics. |
FACTORY_SANDBOX_PREFIX | Fallback sandbox container name prefix. |
FACTORY_STAND_CONTAINER, FACTORY_STAND_FE_CONTAINER | Explicit name templates; {task} is replaced with the task number. |
FACTORY_STAND_URL | Permanent preview URL; does not replace a task sandbox URL. |
FACTORY_TIMER_CMD | Time tracker command. |
FACTORY_TASK_BASE_URL | External task tracker URL base. |
The canonical final ship node enables a delivery contract. Actions depend on project policy and attempt permissions. In a PR workflow this means a commit, pushing the task branch and creating or updating a PR against profile_delivery_targets. The optional task-comment action permits a tracker comment with links.
SHIP alone does not promise a PR merge or deployment. Routes without ship use delivery.mode=disabled and leave delivery to a human.
When changes take effect
| Change | Effect |
|---|---|
| Instructions, nodes, gates, transitions, retries and node policies | Validate and publish a new revision. Existing attempts retain their previous route. |
| Runner, model family, version or effort | CLI update and a compatible host check; used at the next launch decision, never midway through a running process. |
Repositories, workspace mode, branches, services and profile_project_context() | Pinned attempt contract; a mismatch can block continuation. |
| Trusted hooks and lifecycle scripts | Live profile code must remain compatible with older pinned routes. |
Publishing a route does not rebind an existing attempt's environment. A separate profile debug setting changes diagnostic detail, not runners or agent permissions.
After configuration, run profile readiness checks. They do not send a task to a model. Structural and host checks do not replace a trial environment setup and acceptance of a real task.
Continue with configuring stages and runners.