Current architecture contract

Programs code structure

Place deterministic tools in tools/, complete capabilities requiring model reasoning or workflow orchestration in workflow/, and complete products in packages/. Keep only the basic call primitives llm() and agent().

Status: current designScope: source, registration, Programs UI, packaging

1. Canonical directory contract

openprogram/
├── agentic_programming/
│   ├── llm.py                  # single model-call primitive
│   └── agent.py                # Agent-loop primitive with tool calls
└── programs/
    ├── tools/                  # deterministic, directly callable tools
    │   ├── files/  web/  code/  planning/  ...
    ├── workflow/               # all model reasoning, Agent orchestration, and composite capabilities
    │   ├── auto_workflow.py    # complete single-file Workflow; no empty same-name directory
    │   ├── goal/               # single Goal Workflow and session Goal mechanism
    │   │   ├── __init__.py
    │   │   ├── goal.py         # public entry goal()
    │   │   ├── command.py      # /goal command adapter
    │   │   ├── judge.py        # completion-condition evaluation
    │   │   ├── refinement.py   # goal specification and acceptance checklist
    │   │   ├── loop.py         # state transitions, retries, and stop rules of the single loop
    │   │   ├── state.py        # persistent state and events of the same GoalRun
    │   │   └── notices.py      # session status notifications
    │   ├── browser/  document/  research/  ...
    ├── packages/               # independent packages providing callable capabilities
    ├── _registry.py            # shared registration and discovery
    └── _programs.py            # Application provenance and installation metadata
Remove programs/functions/, programs/functions/agentic/, programs/workflows/ or agentic_programming/goal.py. Each capability has one authoritative implementation and one public import path.

2. Three Program categories

programs/tools/

Tools

Ordinary code determines outputs from inputs, without model inference or an Agent loop. Register with @function for reuse by Agents, Workflows, and Applications.

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

programs/workflow/

Workflow

Any capability calling llm(), agent(), other Workflows, or containing multi-stage state and completion checks belongs here. Single-model-call capabilities are also Workflows; there is no separate Agentic Function directory.

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

programs/packages/

Packages

A package is an installation unit for callable capabilities, with its own dependencies and release boundary; it can provide multiple Tools or Workflows. Software Applications use separate management pages, declarations, and registration directories and call public Program capabilities; they are not part of this source classification. Legacy applications/ package locations retain read compatibility.

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

3. Basic primitives and Workflows

EntryMeaningCanonical location
llm()One model call without a tool loop.agentic_programming/llm.py
agent()Model tool-call loop.agentic_programming/agent.py
goal()Repeatedly runs an Agent and checks completion conditions; a complete Workflow, not a third basic primitive.programs/workflow/goal/

4. Goal has one execution function

Single Workflow
from openprogram.programs.workflow.goal import goal is the sole execution function, owning GoalRun initialization, spec refinement, Agent rounds, completion evaluation, user questions, stop rules, state writes, and terminal states. No second Goal loop may remain in the dispatcher, command adapter, or another module.
Programs form
The form directly calls goal(prompt, condition, context_mode="isolated", ...). Run records may belong to the current session, but goal() model context does not read pre-call chat history; it reads only form parameters and calls already produced in this GoalRun.
Chat command
/goal <condition> is only a session adapter for the same Workflow: parse the command, then call goal(prompt=condition, condition=condition, context_mode="session", ...).context_mode="session" reads the current session view at execution start; otherwise it uses the same state machine as the form.
State and control
Both entry points produce identical GoalState, progress events, GoalChip, questions, cancellation, clear/status, and terminal states./goal clear controls the GoalRun associated with the current session, without starting or maintaining a second Goal object type.
Internal modules
judge.py, refinement.py, state.py, loop.py serve only this function.command.py only parses set/status/clear and constructs one goal() call. It does not create state, refine goals, or run continuation.
No duplication
Do not retain continue_goal_turns() and goal() as two round controllers. Do not copy spec/checklist from session Goal to isolated Goal or change default rounds, need_user, or terminal semantics based on entry point.
Public pathOnly permitted differenceMust remain identical
Programs → Use → Goal formcontext_mode="isolated"GoalState, refinement, judge, loop, round budget, questions, cancellation, events, terminal states, and return values
Chat composer → /goalcontext_mode="session"
Result ownership and model context are separate fields: form runs may write DAG/runtime cards into the current session, but must still use render_range.callers=0 to isolate pre-call history. Session commands restore current chat evidence through explicit session-context input.

4.1 Implementation and verification records

TypeConfirmed evidence
Implementation0629e2fd and preceding commits removed Goal continuation from the dispatcher; /goal constructs one goal(..., context_mode="session") forced call. The Programs form still calls the same function and defaults to isolated.
Independent specification reviewPassed. Review covered the single function, both context modes, clear races during refinement/judge, round budgets, and terminal states.
Independent quality reviewPassed. Review covered cancellation, exceptions, questions in the final round, cross-process Goal events, and Web/CLI adapters.
Automated verificationFocused Goal/Programs/Web/CLI/process-bridge suite 116 passed; Web unit tests 54 passed; TypeScript tsc --noEmit, Ruff, documentation links, and git diff --check passed.

This section records reviewed implementation evidence only and does not alter the design contract above.

5. Choosing files and directories

FormWhen to useExample
Single .pyOne public entry and a few local helpers; the file can be read independently.workflow/auto_workflow.py
Same-name packageMultiple modules with distinct responsibilities, resource files, or session adapters.workflow/goal/, workflow/browser/
Internal directoryShared implementation serving only adjacent Workflows; its name begins with _ and it does not become a Programs UI node.workflow/_runtime/

Do not create same-name folders for every Workflow merely for uniformity. File count and responsibility boundaries determine package splitting.

6. Permitted dependency directions

CallerAllowedForbidden
ToolStandard library, approved dependencies, and deterministic helpers.llm(), agent(), Workflow, Application.
WorkflowTools, llm(), agent(), other Workflows without dependency cycles.Depending on Applications, copying other Workflows, or dispatch by string name.
ApplicationPublic Tools, public Workflows, and the application’s own UI and services.Modifying the called Program or maintaining a second implementation.

7. Registration and Programs UI

Shared registration
_registry.py loads public entries from tools/ and workflow/; Applications use provenance records and installation contracts.
Top-level UI
Show only Tools, Workflow, Applications, without historical levels such as Functions, Vanilla, or Agentic Function.
Entity recognition
A registered entry is runnable, so the Programs sidebar shows Use. Expanding a same-name package lists responsibility modules from the actual directory (such as goal/command.py). These files can be opened to inspect call relationships but are not registered as additional Programs and have no Use action.__init__.py and _ internal directories still do not become nodes.
Canonical path
After migration, only new imports are supported. Old paths fail directly, with no aliases or dual scanning of old and new directories.
Stable contract
Moving source does not change public names, parameter Schemas, permissions, DAG semantics, or session state formats.

8. One-time migration acceptance

Migration itemTarget state
functions/vanilla → toolsAll deterministic tools register from new paths; old directories are absent.
functions/agentic + workflows → workflowModel capabilities and composite flows load only from singular workflow/.
Goal consolidationagentic_programming exports only llm, agent; Goal exists only in workflow/goal/.
CallerPython imports, registries, CLI, Server, Web Programs, documentation, and packaging configuration all use new paths.
Old structureNo old directories, compatibility modules, duplicate decorator registrations, or dual-path scanning.
FunctionalityPublic names and Schemas remain unchanged; Goal, Auto Workflow, Programs browsing, and run entry points remain usable.

9. Excluded designs

No new decorators

Do not add @workflow; directories and metadata express classification.

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

No string-based dispatch

Workflows use ordinary Python imports and calls, without adding call_workflow(name).

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

No parallel structures

Do not keep versioned old/new directories or choose between them at runtime.

Portable package sources

Project-local Programs record locations as relative paths scoped by programs. An external installation binding connects the installed runtime to the source checkout. Relative paths do not use the chat working directory. Only exact authorized package names participate in Python resolution; the entire external directory is not added to import scope. Migration, rejection conditions, and publishing rules follow the Workflow package contract.

Source, registry, Programs explorer, and /goal all load according to this page’s directory contract. Source moves do not change public names or Schemas.

Installed Wiki prompt substitutions

The installed wiki_agent generation and enrichment prompts substitute only their declared content fields. Literal CSS examples such as alert-{info|warning|success|error} survive Python formatting unchanged; they are not substitution fields. Ingest and enrich reach their existing model and owned-vault operations without a formatting exception from the default prompt. The repair escapes those two literals in the existing prompt strings and preserves the Wiki generation, slot, Git and index mechanisms. Public acceptance invokes the actual registered entry for both actions, observes the unchanged literal at a controlled generation boundary, and verifies owned page and slot writes. The prompt literal repair has passed independent specification and quality reviews and is imported into the local package. Combined source and installed-interface acceptance are recorded separately.

Dynamic tool argument mappings

Canonical tool schemas distinguish mappings whose keys are provided at invocation time from objects with declared fields. The public program.args mapping accepts a registered program's legal keyword arguments, including task. Anonymous object mappings and Python dict/Mapping annotations retain open keys and any declared value schema. Objects with properties, including an empty declared property set, retain fixed-field closure. Explicit additionalProperties: false is never opened; nullable mappings retain their existing null behavior. Existing implicit-open top-level parameter objects are not newly closed by this repair.

Canonical objectLocal validationProvider tool mode
Anonymous or typed mappingAccept legal dynamic keys; enforce object and declared value typesPreserve the mapping schema with non-strict tool mode
Declared fixed fields or explicit closed objectRetain required fields, types and closed-field rejectionRetain the existing strict mode when supported
Mixed request containing both tool kindsValidate each call against its canonical schemaSelect mode per tool; no request-wide disabling of strict validation

The shared provider schema adapter must not turn an open mapping into an empty closed object. OpenAI function calling requires closed objects for strict mode and documents explicit strict: false to preserve non-strict behavior in Responses. Dynamic-mapping tools therefore use that explicit flag for Responses, Codex and Chat Completions; compatible fixed-field tools continue to use strict mode. Anthropic strict tool use similarly applies strict validation per tool; mapping tools retain the ordinary input schema without the strict flag. Existing provider availability, authentication, request-level feature gates and other schema dialects remain unchanged.

Acceptance uses the real public schema, production local validator and registered program consumer in an owned session. Valid task arguments reach the consumer; foreign programs and unsupported child keywords retain their existing errors, and wrong mapping types or values remain invalid. Production provider payloads preserve a dynamic mapping while a closed companion tool remains strict. The fixed execute_code schema remains strict and no dynamic parameter is added to it. Tests include fixed-object extra-key rejection, nullable and typed nested mappings, nonmutation, affected provider/program suites and repository contracts. Existing live sessions, App, worker and user state are excluded from controlled testing.

Implementation state: the canonical design is complete; implementation, independent specification review, fresh quality review and separate installed acceptance are pending.

Wiki change metadata

Public Wiki ingestion reports the actual touched and created content pages, including pages inside newly created directories and paths containing Unicode, spaces or quotation marks. Change discovery requests individual untracked files and consumes Git porcelain records with NUL delimiters, preserving exact path spelling rather than decoding display quoting or splitting filenames on an arrow string. Rename records consume their paired original path while retaining the destination. Existing content-page suffix, folder-index exclusion, file-existence and Git-ignore rules remain; no unrelated link, page, template, generation, commit or index behavior changes.

Acceptance creates a new nested page through the registered ingestion entry, verifies its slot, actual Git commit and searchable index, and checks nonzero page and folder metadata passed to the existing conclusion step. Owned Git cases verify Unicode and special paths, renames, ignored files and excluded folder indexes. The original dirty ops file is preserved in a dedicated input-baseline commit. The path discovery and reindexing repair has passed independent specification and quality reviews and is imported into the local package. Combined source and installed-interface acceptance are recorded separately.