@klok-integration/cli 0.5.0 → 0.6.205
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/THIRD-PARTY-NOTICES.md +38 -0
- package/assets/agents/AGENTS.documentation.md +3 -2
- package/assets/agents/AGENTS.integration.md +10 -7
- package/assets/agents/AGENTS.workspace.md +143 -39
- package/assets/agents/knowledge/README.md +8 -9
- package/assets/agents/knowledge/glossary.md +1 -0
- package/assets/agents/knowledge/platform-rules.md +38 -8
- package/assets/agents/knowledge/retired-patterns.txt +4 -0
- package/assets/agents/knowledge/roles/integration-architect.md +3 -0
- package/assets/agents/knowledge/roles/integration-developer.md +11 -2
- package/assets/agents/skills/klok-datamodel/SKILL.md +9 -3
- package/assets/agents/skills/klok-docs/SKILL.md +8 -6
- package/assets/agents/skills/klok-release/SKILL.md +25 -19
- package/assets/agents/skills/klok-route/SKILL.md +22 -10
- package/assets/agents/skills/klok-solution/SKILL.md +88 -0
- package/assets/agents/skills/klok-worktree/SKILL.md +7 -2
- package/dist/cli.js +7 -7
- package/package.json +1 -1
|
@@ -166,7 +166,12 @@ custom route for a plain mapping, a plain protocol bridge or an API.
|
|
|
166
166
|
|
|
167
167
|
`KlokSubRoute` splits a route into reusable parts through `configureSubroute(ProcessorDefinition<?>)`; its URI is
|
|
168
168
|
`direct:<fully qualified class name>`. A sub route that only transforms and is called from several onramps is
|
|
169
|
-
right; a sub route that opens an SFTP connection is in the wrong place.
|
|
169
|
+
right; a sub route that opens an SFTP connection is in the wrong place. A sub route has no error handling of its
|
|
170
|
+
own (klok-quarkus-extension 3.4 and later): every exception it throws reaches the route that called it, and that
|
|
171
|
+
route's retries, dead letter queue and reply decide what happens to the message. In a sub route, catch only what is
|
|
172
|
+
not an error (a lookup that finds nothing when "absent" is a valid answer) and handle it, or catch an error to throw
|
|
173
|
+
it again as a more specific `Klok4XXException` / `Klok5XXException` or with a better message. Never give a sub route
|
|
174
|
+
its own `retry.*`, `dlq.*` or `failure.*` keys; configure its caller.
|
|
170
175
|
|
|
171
176
|
## Channel adapters and APIs
|
|
172
177
|
|
|
@@ -194,7 +199,8 @@ blindly. `klok-mock-*` headers are for test and staging and are stripped in prod
|
|
|
194
199
|
2. **Reuse.** Before a new model, search the existing class B and C models, topics and routes, in klok.dev's
|
|
195
200
|
context and on docs.klok.dev. A new topic only for a new contract.
|
|
196
201
|
3. **Solution design.** Solution id from the klok.dev registry, the legs and their route ids, the models per leg,
|
|
197
|
-
`[TACTICAL]` for any deviation
|
|
202
|
+
`[TACTICAL]` for any deviation, written in the solution document before the code and kept current by every change
|
|
203
|
+
of a leg (platform rules, *Solutions*).
|
|
198
204
|
4. **Design per leg.** Base class, exchange pattern, URI, authentication (a Vault path reference, never a secret),
|
|
199
205
|
the `transformBody` sketch, the CloudEvent type, the failure matrix (timeout: retry; invalid: dead letter;
|
|
200
206
|
authentication: alert and dead letter), the tests.
|
|
@@ -215,6 +221,9 @@ blindly. `klok-mock-*` headers are for test and staging and are stripped in prod
|
|
|
215
221
|
routes start and what they publish; never a real broker or OpenSearch in unit tests.
|
|
216
222
|
* Delivery: the `main` pipeline builds the image, updates the deployment manifest that Argo CD applies, and
|
|
217
223
|
publishes the documentation. Never commit hand-made production YAML beside it.
|
|
224
|
+
* Commit messages and merge request titles follow Conventional Commits (`feat(odl): …`, `fix: …`, `docs: …`). The
|
|
225
|
+
pipeline acts on the type: a `docs` merge request only publishes the documentation, so it is `docs` only when
|
|
226
|
+
nothing but `klok-docs/` and root Markdown files changed.
|
|
218
227
|
* Troubleshooting: follow `klok-correlation-id` from ingress through processing to egress; operations follow the
|
|
219
228
|
failure events and the dead letter topics, not pod logs.
|
|
220
229
|
|
|
@@ -34,9 +34,11 @@ domains read should still travel as class B or C (transform at the edge).
|
|
|
34
34
|
ends in `supplier_invoice_v1`. Inside the XSD the model keeps its PascalCase form: root element
|
|
35
35
|
`SupplierInvoice_v1`, root type `SupplierInvoiceV1`.
|
|
36
36
|
|
|
37
|
-
**Create it
|
|
38
|
-
with the
|
|
39
|
-
|
|
37
|
+
**Create it with klok.dev's datamodel wizard.** It pushes a new repository from `project-template-datamodel`
|
|
38
|
+
with the XSD and its `meta.json`, but it does not render the template's `__KLOK_*__` placeholders yet
|
|
39
|
+
(klok/application/frontend-klok-dev#33): check the
|
|
40
|
+
new repository and render any that are left, as below, before relying on its pipeline. The agent at
|
|
41
|
+
https://agent.klok.dev cannot create datamodel projects yet (klok/application/frontend-klok-dev#42).
|
|
40
42
|
|
|
41
43
|
By hand it is: `git clone` the template, `git remote rename origin template`, `git remote add origin <new
|
|
42
44
|
repo>`, render every `__KLOK_*__` token listed in `klok-template.json` (including the XSD file name), push
|
|
@@ -62,6 +64,10 @@ domains read should still travel as class B or C (transform at the edge).
|
|
|
62
64
|
publishes `dev.klok.<tenant>.datamodel:<name>-v<n>:1.0.0-build.<ts>` with its Python and TypeScript packages,
|
|
63
65
|
writes `<nameVn>` (for example `klokOdlV1`) into the dependency catalog, and publishes the documentation payload
|
|
64
66
|
that becomes `<tenant>/documentation/datamodel/<same path>` on docs.klok.dev.
|
|
67
|
+
6. A merged datamodel is not yet a released one. A consumer's `updateKlokLibsToml` waits until the catalog's `main`
|
|
68
|
+
has the commit `chore(catalog): update <name> to the version published by <datamodel repository>@<merge sha>`
|
|
69
|
+
(`Update <name> …` before 2026-10-01). Say so, with the
|
|
70
|
+
command, in the guide that hands the merges over (KLOK-AGENTS.md *Manual steps are handed over as a guide*).
|
|
65
71
|
|
|
66
72
|
## Using a model in a project
|
|
67
73
|
|
|
@@ -31,16 +31,17 @@ drops the `klok-` prefix of the name (`klok-integration-strategy-and-tactics`).
|
|
|
31
31
|
|
|
32
32
|
| Need | Doc id |
|
|
33
33
|
|---|---|
|
|
34
|
-
| Principles, event driven design with sync compatible interfaces, naming cheat sheet, framework map
|
|
34
|
+
| Principles, event driven design with sync compatible interfaces, naming cheat sheet, framework map | `klok-integration-strategy-and-tactics` |
|
|
35
35
|
| Route patterns, capabilities, configuration, logging and correlation, error handling, topics and CloudEvents, async tasks, ODL client, testing, migration from 1.x | `klok-framework-klok-quarkus-extension` |
|
|
36
36
|
| Naming conventions, `klok-*` properties, CloudEvents attributes | `klok-framework-klok-common` |
|
|
37
37
|
| Broker client configuration, subscriptions, request/reply | `klok-framework-klok-brokerclient-java` |
|
|
38
38
|
| Gradle plugin, versions, catalog refresh | `klok-framework-klok-gradle-plugin` |
|
|
39
39
|
| CI templates, release process, Vault roles, documentation chain, catalog update | `klok-environment-build-ci-templates` |
|
|
40
|
-
| Developer rules, prompt catalogue, broker access, identity | `klok-framework-development-guide` |
|
|
40
|
+
| Developer rules, prompt catalogue, broker access, identity, onboarding a tenant | `klok-framework-development-guide` |
|
|
41
41
|
| Concepts, roles, workflow and operations for people | `klok-user-guide` |
|
|
42
|
-
| ODL REST
|
|
43
|
-
|
|
|
42
|
+
| ODL REST facade | `klok-integration-klok-api-odl` |
|
|
43
|
+
| Tasks API | `klok-integration-klok-api-tasks` |
|
|
44
|
+
| ODL services (writes, request/reply, change events), log receivers, task materializer | `klok-integration-klok-egress-opensearch` |
|
|
44
45
|
| Scheduled queries, stale task detection | `klok-integration-klok-ingress-opensearch` |
|
|
45
46
|
| OpenAI compatible API, AI tasks, Kloker gateway | `klok-integration-klok-api-ai` |
|
|
46
47
|
| AI workers, transcription, transcript cache | `klok-integration-klok-egress-ai` |
|
|
@@ -65,7 +66,8 @@ question is about what a project does.
|
|
|
65
66
|
skills you read are the catalogs' current ones.
|
|
66
67
|
2. Identify the repositories involved and derive their doc ids (`klok docs id <path>`).
|
|
67
68
|
3. `klok docs read <doc-id>` for each. Handle 404, 401 and 403 as the table says.
|
|
68
|
-
4. Read the strategy documentation first when the task touches design
|
|
69
|
-
|
|
69
|
+
4. Read the strategy documentation first when the task touches design or naming, and the *Onboarding a tenant*
|
|
70
|
+
runbook in `klok-framework-development-guide` when it touches onboarding; read the framework documentation
|
|
71
|
+
before writing or changing a route.
|
|
70
72
|
5. Cite the doc id and the `fetchedAt` from `klok docs read <doc-id> --json` in your answer or merge request
|
|
71
73
|
description, so reviewers can tell which version of the page you relied on.
|
|
@@ -21,42 +21,48 @@ roles and secrets, catalog update) before acting.
|
|
|
21
21
|
`glab api --hostname git.klok.dev "projects/<id>/pipelines?per_page=3"`, then
|
|
22
22
|
`projects/<id>/pipelines/<pid>/jobs` and `projects/<id>/jobs/<jid>/trace`. Fix a red pipeline before the next task.
|
|
23
23
|
4. Framework changes across libraries are released in order: klok-common, broker client, extension. Wait for the
|
|
24
|
-
catalog update of one before merging the next
|
|
24
|
+
catalog update of one before merging the next: the catalog's commit for that release, not the merge, which only
|
|
25
|
+
starts the pipeline that produces it:
|
|
26
|
+
`glab api --hostname git.klok.dev "projects/klok%2Fframework%2Fklok-gradle-dependency-catalog/repository/commits?ref_name=main&per_page=10" | jq -r '.[].title'`.
|
|
25
27
|
5. **Never cancel, stop or restart a running job, pipeline or deployment without a human's explicit yes.** A
|
|
26
|
-
release waiting on Maven Central or npm can take half an hour, and
|
|
27
|
-
long
|
|
28
|
+
release waiting on Maven Central or npm can take half an hour, and `main` pipelines queue behind each other or run
|
|
29
|
+
in parallel, so a long wait is normal. Check the current time with `date -u` before judging how long anything has run. Report the
|
|
28
30
|
job id, its run time, the last log lines with timestamps and what waits behind it, propose what to do, and wait.
|
|
31
|
+
6. Merging is the human's step. Hand it over as KLOK-AGENTS.md *Manual steps are handed over as a guide* says:
|
|
32
|
+
every merge request with its link, whether the order matters and why, and for each later step the release
|
|
33
|
+
result to wait for and the command that shows it.
|
|
29
34
|
|
|
30
35
|
## Creating a new project
|
|
31
36
|
|
|
32
|
-
**Create projects through klok.dev
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
**Create projects through klok.dev**; the agent at https://agent.klok.dev asks klok.dev to do it. Creating a
|
|
38
|
+
project by hand — `glab api POST /projects`, or cloning the template and swapping the remote — is a legitimate
|
|
39
|
+
fallback under *Git är sanningen*.
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
a red pipeline. Vault CI login is not one of them: it needs nothing per project.
|
|
41
|
+
Neither path provisions a pipeline schedule yet, nor for a deployed service the manifest, its Vault objects, its
|
|
42
|
+
Keycloak client and its broker grants (see below; tracked in klok/application/frontend-klok-dev#41 and #42). Name
|
|
43
|
+
those human steps up front instead of letting them surface
|
|
44
|
+
as a red pipeline. Vault CI login is not one of them: it needs nothing per project.
|
|
41
45
|
|
|
42
46
|
## Setting up a new project (what must exist)
|
|
43
47
|
|
|
44
48
|
* Nothing in Vault per project. Every job logs in with the tenant CI role `<tenant>-ci` (a Vault JWT role bound
|
|
45
49
|
to `namespace_path` `<tenant>` and `<tenant>/*`, carrying `default` and the tenant CI read policy
|
|
46
50
|
`<tenant>-cicd-read`). The templates set `VAULT_AUTH_ROLE: $KLOK_TENANT-ci`. A tenant without the role fails
|
|
47
|
-
every job at `auth/jwt/login` with `role "<tenant>-ci" could not be found`; the tenant setup is
|
|
48
|
-
`klok
|
|
49
|
-
that uses it in `klok-docs/ci/authentication.md`
|
|
51
|
+
every job at `auth/jwt/login` with `role "<tenant>-ci" could not be found`; the tenant setup is the
|
|
52
|
+
*Onboarding a tenant* runbook in `klok docs read klok-framework-development-guide`, every credential and the step
|
|
53
|
+
that uses it in `klok-docs/ci/authentication.md` of `klok/environment/build-ci-templates`.
|
|
50
54
|
* For anything the pipeline resolves from a package registry (framework, plugin, datamodels): the project's
|
|
51
55
|
top-level group must be on the package project's job token allowlist.
|
|
52
|
-
* For a deployed service: a manifest
|
|
53
|
-
Kubernetes role `<name>-role` with
|
|
54
|
-
|
|
56
|
+
* For a deployed service: a manifest `<project path>/<name>-crds.yaml` in the manifests repository, written by
|
|
57
|
+
hand before the first deploy, with the Kubernetes service account; a Vault Kubernetes role `<name>-role` (with
|
|
58
|
+
`audience=https://kubernetes.default.svc`) and its policy `<name>-policy` reading
|
|
59
|
+
`secret/data/<tenant>/integration/<name>/env`; the env secret itself (broker credentials, service specific
|
|
60
|
+
keys); and the service's own Keycloak client with its broker grants.
|
|
55
61
|
* Documentation projects need the tenant's docs upload client: Keycloak client `klok-docs-upload-<tenant>` and its
|
|
56
62
|
id and secret in `secret/<tenant>/common/repo/cicd-environment-variables`.
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
field, and let
|
|
64
|
+
Agents never write to Vault: propose the exact `vault write` / `vault policy write` command with every existing
|
|
65
|
+
field, and let a person run it.
|
|
60
66
|
|
|
61
67
|
## Common failures and their meaning
|
|
62
68
|
|
|
@@ -6,7 +6,10 @@ description: Write or change a Camel route on the Klok Quarkus extension 2.0 (on
|
|
|
6
6
|
# Writing a Klok route
|
|
7
7
|
|
|
8
8
|
Read `klok docs read klok-framework-klok-quarkus-extension` first (pages `patterns`, `naming`,
|
|
9
|
-
`config`, `error-handling`, `testing`); read the `klok-docs` skill for other pages.
|
|
9
|
+
`config`, `error-handling`, `testing`); read the `klok-docs` skill for other pages. A route is a leg of a solution:
|
|
10
|
+
the `klok-solution` skill finds and updates its solution document, before and after the change. Integration logic is
|
|
11
|
+
a Java route; doing it with the Python or TypeScript broker clients is a `[TACTICAL]` choice the solution document
|
|
12
|
+
motivates.
|
|
10
13
|
|
|
11
14
|
## Steps
|
|
12
15
|
|
|
@@ -24,6 +27,9 @@ Read `klok docs read klok-framework-klok-quarkus-extension` first (pages `patter
|
|
|
24
27
|
6. **Errors.** Throw `Klok4XXException` for caller errors, let retryable failures propagate; the base route logs,
|
|
25
28
|
retries with backoff, republishes to `<topic>_DLQ` and emits the failure CloudEvent. Override `failureHandled()`
|
|
26
29
|
only when the route owns its failures (custom routes that answer HTTP themselves).
|
|
30
|
+
A sub route has no error handling of its own: it catches only what is not an error, may throw an error again
|
|
31
|
+
as a more specific Klok exception, and leaves retries, the dead letter queue and the reply to its caller, whose
|
|
32
|
+
keys you configure (`klok docs read klok-framework-klok-quarkus-extension`, *Error handling*, *Sub routes*).
|
|
27
33
|
7. **Capabilities** as interfaces: `SplitIncomingMessage`, `AggregateOutgoingMessages`, `ClaimCheck`,
|
|
28
34
|
`KlokEmitCloudEventOnSuccess/Failure`, `PersistOutgoingMessages`, `KlokAsyncTaskInitiator`.
|
|
29
35
|
8. **Test** with `@QuarkusTest` and the recording broker client factory: assert the route status is `Started`,
|
|
@@ -34,16 +40,18 @@ Read `klok docs read klok-framework-klok-quarkus-extension` first (pages `patter
|
|
|
34
40
|
or standards several routes read, shared mappers, domain logic used by several routes. Each gets its own generated
|
|
35
41
|
page; write its Javadoc for a reader who has not seen the code. Not every class: the classes a route calls
|
|
36
42
|
directly reach its generated documentation without the annotation.
|
|
37
|
-
10.
|
|
43
|
+
10. Update the solution document when the route is new or its contract changed (`klok-solution` skill).
|
|
44
|
+
11. Build (`./gradlew build`) in the task worktree (`klok-worktree` skill), push its `agent/<task-id>` branch,
|
|
38
45
|
open a merge request ready for review, check the pipeline.
|
|
39
46
|
|
|
40
47
|
## Topic purpose
|
|
41
48
|
|
|
42
49
|
A topic is named after its datamodel: `<Model>[_<purpose>]`. The purpose (called *producer intention* in older code)
|
|
43
|
-
is
|
|
44
|
-
|
|
45
|
-
`
|
|
46
|
-
sides from the model and
|
|
50
|
+
is an optional suffix that belongs to the publisher: the solution requires it, the producer sets it, and the consumer
|
|
51
|
+
sets the same purpose on its own route, so one general datamodel serves several flows:
|
|
52
|
+
`CallAiResponseV1_documentation` and `CallAiResponseV1_invoicecoding` both carry the typed `CallAiResponseV1`, and
|
|
53
|
+
each consumer receives only its own flow. The framework builds the full topic name on both sides from the model and
|
|
54
|
+
the purpose.
|
|
47
55
|
|
|
48
56
|
* **When.** Give a flow a purpose when its datamodel is, or may be, used by another flow. Without one, every consumer
|
|
49
57
|
of the model receives every message. No purpose only when every consumer wants every message.
|
|
@@ -63,8 +71,12 @@ sides from the model and the purpose.
|
|
|
63
71
|
Put it in code when the purpose is part of what the route is; put it in configuration when the same route serves
|
|
64
72
|
several flows. Set `<SolutionId>.topic.purpose` only when every route of the solution is on that flow.
|
|
65
73
|
* **Name** the flow as both sides understand it (`created`, `reminder`, `documentation`): letters, digits, `-` and
|
|
66
|
-
`.`, never `_`, and no version
|
|
67
|
-
|
|
74
|
+
`.`, never `_`, and no version or environment. Task types are `<domain>.<verb>-<object>`.
|
|
75
|
+
* **One purpose, no reader.** A topic has at most one purpose. A reader, also one in another tenant, is identified by
|
|
76
|
+
its subscription, whose name is its route id (`DEG012E1_...`; `<RouteId>.subscription.name` overrides it), and never
|
|
77
|
+
adds a suffix to the topic. When the content belongs to one reader, the publisher may choose that reader's tenant
|
|
78
|
+
slug as the purpose (`PersonnelScheduleExportV1_degerfors`); that is the publisher's choice, not something a reader
|
|
79
|
+
in another tenant needs.
|
|
68
80
|
* **A mismatch fails silently**: the two routes end up on different topics and nothing arrives. Check the start log
|
|
69
81
|
(`Route <RouteId> subscribes to <topic>`, `Route <RouteId> publishes <Model> to <topic>`) and assert the full topic
|
|
70
82
|
in the test.
|
|
@@ -83,8 +95,8 @@ explains the reasons and the naming in full.
|
|
|
83
95
|
* Publishing to a hand written topic string; use the resolver and the datamodel.
|
|
84
96
|
* Consuming a shared topic and discarding the messages of other flows (a filter on a payload field, an ODL lookup
|
|
85
97
|
per message) where the producer could publish the flow with a topic purpose.
|
|
86
|
-
* A purpose with `_`, a version
|
|
87
|
-
other side.
|
|
98
|
+
* A purpose with `_`, a version or an environment in it, a second suffix after the purpose, a tenant in it that the
|
|
99
|
+
publisher did not choose, or a purpose guessed instead of agreed with the other side.
|
|
88
100
|
* Choosing a tenant, index, repository or account from a field in the message; the topic decides the tenant.
|
|
89
101
|
* Sharing broker credentials between services, or granting a whole namespace of another domain or tenant.
|
|
90
102
|
* Publishing into another tenant's namespace, with `<RouteId>.topic.tenant-override` or otherwise; a route consumes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: klok-solution
|
|
3
|
+
description: Design, build or maintain a Klok integration solution and keep its solution document true to what is built. Use whenever a task asks to design or develop a service, integration, API or route, to change, fix or extend an existing one, or to explain how a flow is built — before the first route of a new solution and on every change of a leg.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Designing and maintaining a solution
|
|
7
|
+
|
|
8
|
+
New development and maintenance follow one process. A **solution** is the business level unit that a set of
|
|
9
|
+
integration legs belongs to; its **solution document** (`README.md` in the tenant's `integration-solutions`
|
|
10
|
+
registry) says what the legs are, how they interact and why. The document is written before the code of a new
|
|
11
|
+
solution and is brought to the new steady state by every change of a leg, so that the registry describes the
|
|
12
|
+
integration landscape as it is built and deployed, not as it was once planned.
|
|
13
|
+
|
|
14
|
+
Read first: the registry's own `README.md` on `main` (the section list of a solution document, the classification
|
|
15
|
+
of services, the descriptor contract), `klok docs read klok-integration-strategy-and-tactics` (*From solution
|
|
16
|
+
documents to design documents*, *Event driven with sync compatible interfaces*) and
|
|
17
|
+
`klok docs read klok-framework-klok-quarkus-extension`. Reference examples:
|
|
18
|
+
`solutions/KLK010_personnel_scheduling_services/` (two systems) and `solutions/KLK008_ai_image_generation/` (a
|
|
19
|
+
shared platform service) in `klok/integration-solutions`.
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
1. **Find the solution.** The route id prefix is the solution id (`KLK010I1_…` belongs to `KLK010`); a project
|
|
24
|
+
names its solution in `klok-system-project.json` (`solutionId`). The document is
|
|
25
|
+
`<tenant>/integration-solutions/solutions/<SOLUTIONID>_<slug>/README.md` on `main` (fetch first). The tenant's
|
|
26
|
+
`<tenant>-context` skill lists solutions, routes and topics (`data/solutions.jsonl`, `data/routes.jsonl`).
|
|
27
|
+
2. **Check that the document is still true** before relying on it: `klok solutions check --root <registry>`
|
|
28
|
+
compares every solution document with the route classes on the default branch of every repository of the tenant
|
|
29
|
+
in the workspace (`klok sync` first). Findings are drift to fix in this task or to file as an
|
|
30
|
+
issue, never to ignore.
|
|
31
|
+
3. **Read the design.** The solution document and any design page next to it, then each project's `klok-docs/`
|
|
32
|
+
(`klok docs read <doc-id>`, `klok docs id <repo path>` gives the id).
|
|
33
|
+
4. **A new solution gets an id and a document before code.** Take the id from the code, not the next free
|
|
34
|
+
number: grep the integration repositories, pushed branches included, and run `klok solutions validate`. Write
|
|
35
|
+
`README.md`, `solution.meta.json` (`generatedBy: "manual"`) and, when the details do not fit, a design page next
|
|
36
|
+
to it, in a worktree of the registry. The sections are listed in the registry README.
|
|
37
|
+
5. **Reuse before building.** Look for an existing solution or platform capability first: tasks and the task API
|
|
38
|
+
(KLK002), the ODL, the AI services (KLK003), mail (KLK006), the claim check, datamodels in the catalog. A
|
|
39
|
+
capability that needs a change to serve the solution is *reused, slight change*, with its own merge request in
|
|
40
|
+
the owning project.
|
|
41
|
+
6. **Classify every service** the solution needs: *new project*, *new routes in an existing project*, *reused,
|
|
42
|
+
slight change*, *reused as is*, *client change*. Name the repository of each.
|
|
43
|
+
7. **Map the legs.** For every route: id (`<TENANTSHORT><NNN><LEG><seq>_<Description>`, leg and sequence not used
|
|
44
|
+
before — `klok solutions check` reports duplicates), project, pattern base class, topics with their purpose,
|
|
45
|
+
datamodels and their class, task types, configuration keys, and how the legs interact (diagrams in the flows
|
|
46
|
+
section). Route configuration and details stay in the project's `klok-docs/`; the solution links there.
|
|
47
|
+
8. **Choose the technology deliberately.**
|
|
48
|
+
* Integration logic is **Java Klok routes** on the Klok Quarkus extension. They are documented by the platform
|
|
49
|
+
with their topics, datamodels and configuration, and related integrations group in one project and reuse its
|
|
50
|
+
services.
|
|
51
|
+
* Integration logic written with the Python or TypeScript broker clients, or kept inside an application, is a
|
|
52
|
+
**`[TACTICAL]`** choice: write the motivation, its cost and the condition for removing it in the solution's
|
|
53
|
+
tactical section.
|
|
54
|
+
* An external engine (a GPU model server, a vendor service) stays **simple and dumb**: it does one request at a
|
|
55
|
+
time over REST. Priority, queues, retries, claim checks and task state live in a Java egress. The engine may be
|
|
56
|
+
written in any language; that is not tactical, logic moved into it would be.
|
|
57
|
+
9. **Order the delivery.** Datamodels and framework changes are released and merged into the dependency catalog
|
|
58
|
+
before their consumers; steps only a person may take (creating projects in klok.dev, Vault, running Ansible,
|
|
59
|
+
merging) are numbered hold points in the document's delivery order. The answer that hands them over is a
|
|
60
|
+
step-by-step guide with the commands, the merge order and the release result each step waits for
|
|
61
|
+
(KLOK-AGENTS.md *Manual steps are handed over as a guide*).
|
|
62
|
+
10. **Build each leg** with the `klok-route`, `klok-datamodel` and `klok-release` skills, every repository in its own
|
|
63
|
+
worktree with the same task id (`klok-worktree` skill).
|
|
64
|
+
11. **Keep the document true.** Every merge request that adds, changes or removes a leg updates the solution
|
|
65
|
+
document in the same change set: the legs table, the flows and the status. A leg that is not on `main` yet
|
|
66
|
+
carries `planned` in the Status column of its table row; `klok solutions check` relies on it. After the merges,
|
|
67
|
+
run `klok solutions check` again.
|
|
68
|
+
|
|
69
|
+
## Maintenance is the same process
|
|
70
|
+
|
|
71
|
+
* A fix or a change in one route starts at step 1: find its solution and read it before touching the code.
|
|
72
|
+
* A change that alters a leg's contract (a topic, a purpose, a datamodel, an API, a task type, a configuration key
|
|
73
|
+
another project reads) updates the solution document as well as the project's `klok-docs/`.
|
|
74
|
+
* When the document and the code disagree, the code on `main` is what is built: correct the document. When the code
|
|
75
|
+
differs from what was agreed, file an issue in the owning project and name it in the document's open questions.
|
|
76
|
+
* The deployed landscape counts too: a leg that is on `main` but not deployed, or deployed from somewhere the
|
|
77
|
+
document does not name, is written down. Deployment manifests are in `klok/environment/ipaas-se-deploy-manifests`,
|
|
78
|
+
hosts and stateful services in the Ansible inventories of `klok/environment/klok-environment-setup`.
|
|
79
|
+
|
|
80
|
+
## Things that are always wrong
|
|
81
|
+
|
|
82
|
+
* Code for a new solution before its document exists, or a route id whose prefix is not a registered solution.
|
|
83
|
+
* A leg in code that its solution document does not name, or a document that names a leg as built that is not.
|
|
84
|
+
* Reusing a leg and sequence (`KLK002A11`) for a second route.
|
|
85
|
+
* Integration logic in a Python or TypeScript client, or in an external engine, without a `[TACTICAL]` entry.
|
|
86
|
+
* A solution document that describes an unbuilt part in the present tense without saying it is planned.
|
|
87
|
+
* Copying a leg's route configuration or route table details into the solution document instead of linking the
|
|
88
|
+
project's `klok-docs/`.
|
|
@@ -100,12 +100,17 @@ cleanup task, never moved or deleted on the way.
|
|
|
100
100
|
## Finish
|
|
101
101
|
|
|
102
102
|
1. Validate the requested behaviour, inspect the final diff, and commit to the task branch: stage specific paths,
|
|
103
|
-
check for secrets and unrelated files
|
|
104
|
-
|
|
103
|
+
check for secrets and unrelated files, and write the message as a Conventional Commit (`fix(odl): …`; see
|
|
104
|
+
*Commits follow Conventional Commits* in `KLOK-AGENTS.md`). Respect an explicit request to leave changes
|
|
105
|
+
uncommitted.
|
|
106
|
+
2. Push and open a merge request ready for review, with a Conventional Commits title that types the whole change
|
|
107
|
+
(`docs` only when nothing but documentation changed), when the task or the established workflow allows it (see the
|
|
105
108
|
`klok-release` skill for what to check afterwards). Do not invent approval requirements and do not assume a
|
|
106
109
|
permission that was not given.
|
|
107
110
|
3. Report: canonical repository path, worktree path, branch, commits, tests run, push and merge request status,
|
|
108
111
|
remaining changes and the next action. Unfinished work gets a clear handoff and keeps its worktree.
|
|
112
|
+
4. End with the step-by-step guide of everything left for a human, merging the merge requests included
|
|
113
|
+
(KLOK-AGENTS.md *Manual steps are handed over as a guide*).
|
|
109
114
|
|
|
110
115
|
## Cleanup
|
|
111
116
|
|