Changelog
All notable changes to this project will be documented in this file. See commit-and-tag-version for commit guidelines.
[3.2.2] - 2026-10-30
Security
- The corporate proxy and CA were ignored on Node.js 26. Node 26 ships undici 8, whose
fetchreads the global dispatcher from a new symbol; gherkin-ai's undici 6 only set the old one, so withHTTPS_PROXY,network.proxyornetwork.caFilethe LLM traffic went straight to the provider, with the system CA list and no warning.undicimoves to 8, which sets both. Plain-HTTP gateways are now reached through the proxy as forwarded requests (undici 6 opened a CONNECT tunnel).@hono/node-server(via the MCP SDK) is updated for GHSA-rmxm-3fg6-px4f:npm auditreports 0 vulnerabilities.
Added
- The governance commands work on a repository that never ran
ghk init(ADOPTION.md §0). A new golden (tests/golden/brownfield.test.ts, an Express and a Spring service with their own routes and no gherkin-ai file) runs them with stdin closed; 15 of its 18 checks failed on 3.2.1.- Without a project configuration, the defaults are the stack
ghk detectfinds:validatereported an Express service astypescript + nestjs + prisma. convergeleaves Contract Coverage and Architecture Compliance out of the score (n/a, with the reason) when the repository has no configuration, inventory or constitution. They counted as 0% and 50% and made an existing service exit 7. With gherkin-ai's own artifacts nothing changes.converge --openapi <file>measures contract coverage against the repository's own OpenAPI document: a command is covered by an operation whoseoperationIdnames it or whose path ends with its verb.- Nothing is written to such a repository: telemetry and audit go to
~/.gherkin-ai/workspaces/<name>-<hash>/until it has a configuration, and the semantic-model cache (.ghe/cache/ir/) ignores itself in git.
- Without a project configuration, the defaults are the stack
ghk detect --jsonreports the detected stack without prompting or writing a configuration.coverage.commandandcoverage.reporttellghk qualityhow the project measures coverage. The stack default (mvn -B test jacoco:report,npm test -- --coverage, …) left out integration tests that need a database, so an LMS service measured 27–55% instead of 81–93%. The report format follows the file name (Istanbul summary, JaCoCo CSV, coverage.py / coverlet JSON,go tool covertext).quality --jsonreportscoverage.commandSourceandcoverage.warning.qualitywarns whennpm testchains commands (jest && cucumber-js): npm passes the coverage flags to the last one only.ghk generate --contracts-onlywrites only the contracts (OpenAPI, AsyncAPI, gRPC, GraphQL, ADR).- A leading slash anchors a
generation.exclude(andprotect, and firewall path) pattern at the project root, as in.gitignore:/openapi.jsonkeeps the service-wide document but still writescontracts/<feature>/openapi.json. A pattern without a slash still matches at any depth. It did not work before (it never matched). ghk firewall check "<command>"is short for--exec "<command>".- MySQL 8 for the NestJS and Express runtime kernel (
stack.kernelDatabase: "mysql"): the same command service, outbox relay, inbox, sagas and IT1–IT7 suite on MySQL throughmysql2(INSERT IGNORE/ON DUPLICATE KEY UPDATE, outbox claim withFOR UPDATE SKIP LOCKEDin a transaction,GET_LOCKaround migrations, the service's own database by default). Tenant isolation is the repository filter (no row-level security in MySQL). Verified by the goldensexpress-mysqlandnestjs-mysqlagainst MySQL 8.4. MySQL in the other runtimes, and MongoDB, are planned for 3.3 (RUNTIME-KERNEL.md). deploy.base: a shared base stack (AWS; LMS P-06: nine services meant nine RDS instances and nine brokers). Services that set the samedeploy.base.dirshare one RDS instance (a role and a database each, created by an idempotentbootstrap_sqloutput) and one Amazon MQ broker, written once at<dir>/aws; each service module reads its URLs from the base's remote state and joins itsclientssecurity group. Verified by the goldenterraform-aws-base(both modules init, validate and fmt). Google Cloud and Azure report a configuration error for now.deploy.compute: "vm"(LMS P-04): the service on one virtual machine (EC2, Compute Engine or an Azure Linux VM) with the same managed database, broker and secret store ascontainers. cloud-init installs Docker, reads the secrets with the machine identity (never in the user data) and runs the image behind Caddy, with HTTPS whendomainis set; the relay process runs there too. No SSH ports open. Verified by the goldensterraform-aws-vm,terraform-gcp-vmandterraform-azure-vm(init, validate, fmt) and by rendering the boot script for each cloud (DEPLOYMENT.md).stack.role: "bff"(LMS limitations 19 and 24): a backend-for-frontend is generated as a stateless gateway instead of a command service: no runtime kernel, database, outbox, aggregate, seed or AsyncAPI, and no events invented for it. Each feature's commands are exposed atPOST /bff/v1/<feature>/{id}/{command}and forwarded to the service named by@upstream:<name>(bff.upstreams), passing on the caller's token, trace context, Idempotency-Key and request id; 401 without a token, 404 for an undeclared command, 4xx passed through, 502 for a failing or unreachable service, 504 on timeout. Express, NestJS 11/12 and Spring Boot, each verified by a golden build (RUNTIME-KERNEL.md).ghk lint --assist: where the deterministic extraction finds no names (GHK016) and the feature declares no tags, the configured LLM proposes@aggregate,@commandand@eventtags, aligned with the type names already in the code. The answer must fit a JSON schema, and every name must pass rules the model cannot negotiate (PascalCase, a verb first for commands, the past tense for events, no generator defaults, no duplicates). Accepted names become a patch in.ghe/patches/; the feature is never written and the lint result does not change. The deterministic extraction remains the default and the only path in CI.ghk speckit verify: the verification layer under GitHub Spec Kit. For eachspecs/NNN-name/it fails (exit 7) when the spec was never imported, a user story lost scenarios, an FR-### is not in the feature, a task marked done intasks.mdhas no scenario that verifies it, or convergence is below the threshold. It warns whenAGENTS.md/CLAUDE.mdnever send the agent through gherkin-ai's gates.educationindustry profile (LMS P-03): 1EdTech OneRoster 1.2, LTI 1.3 and Caliper; consent of the legal representative before a minor is processed (GHK901, error: Ley 1581, COPPA, GDPR art. 8, LGPD art. 14), access control on education records (GHK902, FERPA), IMS vocabulary (GHK903). The LMS features about minors, guardians and grades pass it (INDUSTRIES.md).- Industry rules over the contracts. The banking, health and telecom profiles also check the OpenAPI document the service exposes (generated, or the repository's own with
--openapi): decimal amounts with an ISO 4217 currency, IBAN/BIC formats and no card data (banking, GHK151–154), FHIRresourceTypeand authentication on operations that carry PHI (health, GHK451–452), TM Forumid/href/@type(telecom, GHK251).ghk validatefails on an error (exit 4);ghk convergescores them under Architecture Compliance (INDUSTRIES.md). ghk audit export --format ocsf: one OCSF 1.3 API Activity event per audit record, for SIEMs that ingest OCSF without a parser (Amazon Security Lake, Splunk, Sentinel, Google SecOps). The field mapping is in ENTERPRISE.md §9.- docs/COMPLIANCE.md maps gherkin-ai's controls (firewall, proposal-first writes, MCP least privilege, organization locks, model pinning, redaction, sandbox, gates, traceability, audit) to ISO/IEC 42001 Annex A, SOC 2 and the EU AI Act, with the code behind each row and what is not covered.
Fixed
ghk detectcrashed without a terminal (ERR_USE_AFTER_CLOSE). With a stdin that is not a TTY, or--json, no command prompts: the defaults are taken, as with--yes.-f/--featureresolved differently in each command. It now takes a path or a feature name everywhere (implement,impact,diff,validate,converge,lint).implement -f <unknown>printed "No feature file found", exited 0 and suggested a file that does not exist; it is now exit 2 with the list of features, as isimpact(was exit 1).lintandconvergepassed when there was no feature (exit 0, also with--json), so a CI job pointed at the wrong--projectwas green. They exit 2;--allow-emptyaccepts a project without features.- Commands named after unknown verbs. "the customer places an order", "the administrator grants access", "the representative revokes consent" produced
unknown_customer_places-style IR commands (shown bygraphasUnknownCustomerPlaces) and the generator'sProcess<Feature>default. An extended verb list (place, submit, grant, revoke, request, open, reserve, invite, confirm, grade, ...; English third person or after "I"/"we", so "the request" is not read as a verb) names themPlaceOrder,GrantAccess,RevokeConsent. It only applies where the verb was unknown: a feature that already produced commands gains none, and no name that 3.2.1 derived from a known verb changes. Of 38 features in the LMS and the reference projects, 6 LMS features change (all fromProcess<Feature>); none of the reference projects does. - Received events were published by the consumer (LMS limitation 3).
Given the "SubmissionGraded" event was receivedmade a published channel in the consumer'sasyncapi.jsonand an event its kernel recorded. Received events (Given/When steps with "was received", "is consumed", "arrives", "se recibe"…, also in the Background) are nowconsumedEventsin the semantic model, listed underinfo.x-ghk-consumesinasyncapi.jsonand never published. - Quoted example data became events. "When the teacher publishes the grade for student "S-1"" made an event channel
…/events/s1. In a Given or When step without the word "event", only a quoted PascalCase name is an event. - Scenario categories depended on the word form: "validates", "validated", "authorizes", "forbids", "denied as unauthorized" and "signed in" now count as validation and authorization (LMS limitation 23).
- The traceability graph ignored domain names shorter than 6 characters (
Grade,Order). Their PascalCase type name is matched as a whole identifier. - Regenerating an up-to-date project changed
.ghe/inventory.json: every entry got a newgeneratedAt, and since 3.2.1 the inventory is versioned. An unchanged file now keeps its date: a secondghk generatechanges nothing in git (checked on the 16 reference projects). risk --baseleft out new files that were not added to git yet; without--basethey were counted.- The generated Angular app had no
servetarget, and every Angular frontend depended on@microsoft/signalrand shipped a SignalR client, which only the ASP.NET Core backend has a hub for.ng serve(npm start) works; the SignalR client is generated for .NET backends only (LMS limitation 22). - Generated FastAPI and Django tests failed with pytest 9.2 (
'FixtureManager' object has no attribute '_arg2fixturedefs'): pytest 9.2 removed an internal that pytest-bdd 9.0, its latest release, still uses. The generatedpyproject.tomlrequirespytest<9.2until pytest-bdd supports it. Existing projects get the cap withghk generateor by editingpyproject.toml.
Project
- Documentation portal and golden dashboard on GitHub Pages (
.github/workflows/pages.yml,scripts/build-site.js): the README, the docs and the CHANGELOG as pages, and a page with every golden build and its result in the CI run onmain(goldens.jsonfor machines). - Governance:
GOVERNANCE.md(roles, decisions, how to become a maintainer, continuity),MAINTAINERS.md,docs/FOUNDATION-READINESS.md(OpenSSF Best Practices criteria with their evidence, and what is missing) and an OpenSSF Scorecard workflow. - Benchmark tasks (
evals/bench/): one orders service in Express, Spring Boot and FastAPI, with the same black-box HTTP acceptance test (9 checks), ready forghk bench run. SUPPORT.mddescribes commercial support offerings.
Changed
- Node.js 22.19 or later (was 22.12), the minimum undici 8 supports. CI also tests Node 26.
- Maintenance tiers.
ghk stacks(andmaintenancein--json) says whether a stack is core (kept current by the maintainers, new runtime features first) or community (kept current through contributions). Both run the same golden builds. No new stacks are added in 3.x (ENTERPRISE.md §11). - npm metadata. The keywords describe the category (spec-driven development, AI governance, agent firewall, drift detection) instead of the frameworks it generates; a package aggregator had listed gherkin-ai as a React charts library. The homepage, the CLI banner and the README point to one documentation URL, https://fennereduardo.github.io/gherkin-ai-cli/.
[3.2.1] - 2026-10-25
Most of these were found by adopting 3.2.0 in an implemented multi-service project (the LMS reference project); the rest by a code-verified security and governance review of 3.2.0. A golden built from one of the LMS services (tests/golden/implemented-service.test.ts, also a CI job that compiles it) keeps the generation fixes; it fails on 3.2.0. Upgrade notes: MIGRATION-3.2.md, "From 3.2.0 to 3.2.1".
Security
zod4.zod3.25.76 is affected by GHSA-mrhx-c7xc-m3w5 (memory exhaustion validating oversized constrained collections, high) and has no 3.x fix;npm audit --audit-level=highblocked the release.zod-to-json-schemais replaced by zod's ownz.toJSONSchema; the published schemas validate the same configurations, except that$schema(whichghk upgradeadds) is now accepted.openaimoves to 7 (version 4 requires zod 3).undici,body-parserandfast-uriadvisories fixed too:npm auditreports 0 vulnerabilities.- Agent firewall: command evasions.
cat .env,cat ~/.ssh/id_rsa,cat a > src/x.ts,ls $(…), a second command after a newline andghk verify --auto-fix --applywere all ALLOW. Commands are now parsed as a shell splits them; files read by a command or a redirection follow the write deny-list; substitutions, expansions, redirections to files, here-documents, background jobs and unquoted globs need approval;ghkis allowed only for read-only subcommands. 48 vectors intests/security/firewall-evasion.test.ts. - One write policy. The repair loops' guardrails and the MCP
ghk_governance_checkdecided paths with their own regexes (one allowed migrations and infrastructure the firewall held, the other blockedsrc/.environment.tsand allowed a rootsecrets.ts). Both now ask the agent firewall, with its glob matcher (tests/security/policy-consistency.test.ts). In theverify --auto-fixrepair loop, specifications, contracts and tests need a human. verify --auto-fixruns in the sandbox container by default (--hostto run on this machine). LLM, cloud and registry credentials are left out of the environment of the code the agent wrote, also with--host.- Release gate.
release.ymlruns the whole CI pipeline on the tag and publishes the tarball the golden builds ran against (npm pack, installed in a clean directory). Every action is pinned by commit SHA; CycloneDX is pinned to 6.0.1.
Fixed
- Generated backends did not create their database tables. In every stack only the HTTP integration tests ran the kernel's
migrate: a service deployed against an empty database answered 500 to its first command (relation "public.ghk_idempotency" does not exist). The golden image smoke did not see it, because it reused the database the integration suite had just migrated. Found by rebuilding the reference projects with 3.2.1.- Every backend now migrates when it starts, before it serves or relays: Spring (Java, Kotlin), Quarkus (Java, Kotlin), NestJS, Express, FastAPI, Django (WSGI and
outbox_relay), Go, Rust, ASP.NET Core, Laravel (once per container, andoutbox:relay), Rails (initializer, also foroutbox:relay) and Phoenix. migrateruns as one statement that first takes a transaction-scoped advisory lock, so replicas starting together do not race on PostgreSQL's catalog.GHK_MIGRATE=falseskips it, for services whose database user has no DDL rights.- The golden image smoke now starts the image against a fresh database.
- Every backend now migrates when it starts, before it serves or relays: Spring (Java, Kotlin), Quarkus (Java, Kotlin), NestJS, Express, FastAPI, Django (WSGI and
ghk upgrade --applyleft an implemented service that did not compile. The new kernel files were created while the edited ones were kept, so the new files called an API the kept kernel did not have.- The runtime kernel (runtime and domain model) is now written as a unit. While a kernel file is kept, every generated source file that would be created or updated is written as
<file>.ghk-newtoo, so the project compiles as before. generatewarns "Runtime kernel pending merge" andupgradereports the findingkernel.pending-merge.- A held file keeps its checksum on record, so it is still provably unedited once the kernel is merged.
- The runtime kernel (runtime and domain model) is now written as a unit. While a kernel file is kept, every generated source file that would be created or updated is written as
.ghk-implementeddid not stopgeneratefrom creating files. In the LMS service, 3.2.0 created 32 of them: a second aggregate, a tenant filter, step definitions that broke Cucumber with ambiguous steps,application.propertiesnext toapplication.yml, aHealthControllerand 10 DTOs.- In a project marked as implemented, only the runtime kernel and the contracts are created. Everything else is reported as
skipped;--include-scaffoldcreates it anyway. ghk addis unchanged: it creates its files.
- In a project marked as implemented, only the runtime kernel and the contracts are created. Everything else is reported as
- Second DataSource and outbox relay in implemented services (also with
upgrade --kernel). The kernel wiring is never created in a project marked as implemented:RuntimeConfiguration,RuntimeProducers,OutboxRelayWorker,DatabaseUrlConfigSource, the NestJSruntime.module.ts, the Laravel provider and command, and the Elixir and Rails relay workers. upgrade --applydeletes no source files in an implemented project. Stale generated source files are reported ingenerated.stale-kept(hand-written code may still use them).--prunestill deletes them.ghk qualitypassed its gate when the tests failed or no coverage could be read (exit 0,gatePassed: true).- Failing tests now always fail the gate (exit 4), even when a report from an earlier run is on disk.
- A missing coverage figure fails the gate unless
--allow-missing-coverage.
ghk qualitycoverage was not reproducible. The report is deleted before the tests run; for Maven, so istarget/jacoco.exec, which JaCoCo appends to.- The JSON records
coverage.command,coverage.exitCode,coverage.reportPathandcoverage.reportMtime. Kotlin and Gradle builds are measured too (they were "not supported").
- The JSON records
ghk qualityfailed 7 of 9 unchanged LMS services on risk alone. Without a change set (no--base, clean tree) the risk describes the whole specification: it is reported (risk.gating: false) but no longer gates.--base <ref>gates on the risk of a change. The risk score uses the coveragequalityjust measured instead of "no coverage report".verify --auto-fixleft the agent's changes behind when the circuit breaker, a stop rule or an error ended the loop, and never removed the files it created. Whatever ends the loop without passing tests, every file it wrote is restored and every file it created is removed.- Proposals collided by file name.
src/button.tsandcomponents/button.tsboth becamebutton.ts.proposed. Proposals are now unified diffs named after the relative path:.ghe/patches/src__button.ts.patch(git applytakes them), inverify,autopilotand the firewall. - Made-up metrics.
verifyandautopilotwrote a fixed requirement coverage (10/10, 0/10 or 5/10) to.ghe/execution/metrics.json. It is now the requirements of the project's features that a test references (requirementCoverageMethod: "specification-traceability"), ornullwith"unavailable". - A fresh clone could overwrite edited code.
.ghe/was ignored, so a clone had no inventory, and a file with aGenerated by gherkin-aiheader was overwritten even if edited. The.gitignorenow keeps.ghe/inventory.json(.ghe/*,!.ghe/inventory.json; existing.ghe/entries are migrated), and without an inventory a header alone no longer allows overwriting (.ghk-new, unless--force;upgrade --applystill trusts headers on its own branch). ghk upgradesaw nothing generated in projects whose files carry no header (most 3.x files): it now reads the inventory too (generated.inventory-only), and the inventory records the CLI version (cliVersion).- Names from the words of the steps.
the teacher "t-7"orbecause "late"producedTeacherDTO,BecauseDTOandteacher/becausecolumns inseed.sql. Field DTOs and seed columns now come from DataTable headers only; conjunctions and prepositions (because,porque, ...) are never fields. application.propertiesnext toapplication.yml. Not created when the project's YAML exists (Spring and Quarkus read both).- No coverage in generated JVM builds. Maven POMs (Spring, Quarkus) and Gradle builds (Kotlin) include JaCoCo, with the report written after the tests, where
convergeandqualityread it. - Node.js older than 22.12 ran the CLI without a warning (
enginesis only checked by npm). The CLI now exits 2 and names the version it found. ghk converge -f <file> --jsonexited 0 below the threshold; it exits 7 like the text output.
Added
- Contract drift checks in
ghk converge(pass/fail, next to the score). In the LMS mutation protocol, converge scored 62 for the untouched service and for every mutation, including a state renamed in the feature only and a route renamed in the controller only.spec-changed: the feature was edited after it was generated from, and its contracts were not (the inventory records the feature's and the contracts' checksums). Exit 7.live-contract(--live <file|url>, e.g.http://localhost:8080/v3/api-docs): contract operations the running service does not serve. Exit 7. Operations it serves but the contract does not list are reported.spec-states: states the feature spells out (status "DRAFT") that no enum of the contracts lists. Reported; exit 7 with--strict-contracts.
- Step coverage in
ghk validate -f <feature>. Steps that no step definition matches (Cucumber expressions and regular expressions, in every language the step indexer reads) are reported;--strict-stepsfails on them. - Feature scope for agent writes.
verify --auto-fix -f <feature>limits the repair loop's writes to that feature's impact scope (the repository graph, asghk firewall check --featuredoes; writes outside it become proposals), andautopilotdoes the same for the bindings once the specification is on disk. generation.exclude. Globs from the project root thatgenerate,addandupgrade --kernelnever write: no create, no update and no.ghk-new.- Skipped files are recorded in the inventory (
skipped: true, with the previous checksum kept), soupgradedoes not prune them as stale.
- Skipped files are recorded in the inventory (
ghk generate --json. Prints the write plan, also with--dry-run:{plan: [{file, target, action, role, reason, held}], summary, kernelPendingMerge}. Before, the plan was only text on stderr.SECURITY.md: third-party dependencies. What a supply-chain scanner reports for gherkin-ai (network and shell access,protobufjs,node-domexception) and why.
[3.2.0] - 2026-10-23
Added
- Deployment targets (
deployin the configuration): Terraform for AWS, Google Cloud and Azure, and a Helm chart. Seedocs/DEPLOYMENT.md.deploy.cloud.aws: ECS Fargate behind an ALB, RDS PostgreSQL, Amazon MQ for RabbitMQ, Secrets Manager and CloudWatch Logs.gcp: Cloud Run with Direct VPC egress, Cloud SQL PostgreSQL on a private IP, Pub/Sub, Secret Manager.azure: Container Apps, PostgreSQL Flexible Server, Service Bus with Entra ID (or an external RabbitMQ), Key Vault and Log Analytics.
- Network as input. The service runs in your existing VPC or virtual network.
- Per environment. One
.tfvars, one remote-state backend file and one Helm values file per environment. Inprod, deletion protection, high availability and longer backups are turned on. - Secrets. Terraform generates them and stores them in the cloud's secret manager: the database and broker URLs,
JWT_SECRET, and the framework secrets. - Least privilege. The service identity can only publish to and consume from its own Pub/Sub topics and subscriptions or its Service Bus entities.
deploy.compute: kubernetes | both. A Helm chart for EKS, GKE or AKS:- probes and a restricted security context;
- HPA, PodDisruptionBudget and an optional Ingress;
- a ServiceAccount with the workload-identity annotation;
- secrets from an existing Secret (External Secrets or the CSI driver).
- Separate relay. Django, Laravel and Rails get their outbox relay as a separate process on each platform.
- Goldens.
terraform-aws,terraform-gcp,terraform-azureandterraform-azure-rabbitmqrunterraform validateandfmt -check;helmrunshelm lint --strictandhelm templatefor every environment. Nothing is applied.
- Every backend exports its traces. Before, spans were created but never left the process, except in Quarkus.
- When. With
OTEL_EXPORTER_OTLP_ENDPOINTset, every backend exports over OTLP/HTTP, batched, withservice.namefromOTEL_SERVICE_NAME. Without it nothing is exported and nothing connects. - How. Each stack uses its official SDK: Node, Java, .NET, Python, Go, Rust, Ruby, Elixir and PHP.
- Shutdown. Rust now shuts down gracefully on SIGTERM and flushes its spans.
- Collectors. The generated Terraform runs a collector sidecar: ADOT to X-Ray and CloudWatch on AWS,
googlecloudto Cloud Trace,azuremonitorto Application Insights. It has the matching permissions and anenable_tracingswitch. - Golden check. The image smoke test sends one command with a JWT and requires its spans to reach an OpenTelemetry collector.
- When. With
- CI/CD pipelines (
ci.provider:github,gitlab,azure-devops). Opt-in; GitHub Actions is the default whendeployis set.- Every provider. Specification gates (gherkin-ai pinned), build and tests in the stack's toolchain image, the runtime integration suite against PostgreSQL and RabbitMQ, the production image, a Trivy scan and a CycloneDX SBOM.
- GitHub Actions also deploys. One environment after another, with protection rules, OIDC to AWS, GCP or Azure, image push, Terraform or Helm, and a readiness smoke test.
- Verification.
actionlintand the official GitLab and Azure Pipelines schemas, in goldens.
- Deployment readiness for AI agents.
- Context files.
.ghe/deployment-context.mdand.jsonhold the runtime contract, the target, the rules and a checklist. A Deployment Readiness section goes into theimplementprompt and the agent prompts. - Validation.
ghk validatechecks the Dockerfile (non-root user, no secrets),.env.example, and hardcoded secrets indeploy/. - Firewall. Changes to
deploy/**,*.tfvars,*.tfbackendand Dockerfiles in subdirectories require human approval. .env.example. It lists the framework secrets (APP_KEY,SECRET_KEY_BASE,DJANGO_SECRET_KEY).
- Context files.
- Explicit model tags and
ghk lint --explain-ir(4.2).- Tags.
@command:Nameand@event:Name, on the feature or on a scenario, name the commands and events in the semantic model (inferenceSource: user) and in the generated code, in any Gherkin dialect. Before, non-English features always got one genericprocess_<aggregate>command. - GHK016 (info). It reports the features whose commands can only be named generically.
--explain-ir. It prints the aggregate, route, commands and events with the source of each name, and the tags that make them explicit (also in--json).
- Tags.
ghk report: gherkin-ai results on pull and merge requests (4.7). It runs lint, converge and risk and publishes the results with no token or extra permission.- GitHub. Annotations on the
.featurelines of the pull request, and a summary of scores and delivery risk in the job summary. - GitLab. A Code Quality report for the merge request widget.
- Gate. It exits 4 below the lint threshold or at
--fail-on. - Generated pipelines. The GitHub Actions and GitLab CI pipelines use it.
- GitHub. Annotations on the
- Deterministic repair in
ghk verify --auto-fix(4.5). Before calling the LLM, rules decide on failures with a mechanical cause. Each rule fires at most once per run.- Fix. For a missing dependency or an out-of-sync lockfile, it runs the toolchain's dependency command (
npm install,go mod tidy, ...) when the firewall allows it, then runs the tests again. - Stop. When the integration tests have no database or broker, or newer
.ghk-newversions are waiting next to edited files, it explains what to do (--services,ghk generate --review) instead of spending model calls.
- Fix. For a missing dependency or an out-of-sync lockfile, it runs the toolchain's dependency command (
- Calibrated risk weights (4.4).
- Configuration.
policy.risk.weightssets the weight of each of the six risk dimensions, normalized to sum 1. ghk risk --calibrate [--commits N] [--write]. It proposes the weights from the git history:- a commit is risky when a fix, hotfix or revert touches its files within the next 10 commits;
- each dimension's weight grows with how much higher it scores on risky commits;
- the result is blended with the defaults in proportion to the evidence;
- the report shows the mean score of each dimension on risky and on other commits.
- Configuration.
ghk generate --review(4.10). It resolves the<file>.ghk-newversions next to edited files.- Per file. It shows the diff, then takes the generated version or keeps yours.
- Keep yours. The version you keep is recorded in
.ghe/inventory.json.generatedoes not offer the same content again, only a different one. - Non-interactive.
--accept-newand--keep-mineresolve every file at once. Otherwise the command exits 4 while versions are pending.--jsonlists them.
- Traceability markers in
ghk graph(4.3).- Aggregate. The aggregate name and its class (
<Aggregate>Aggregate) are symbols of their feature. Theghk:implements <Aggregate>markers of the generated controllers, and the aggregate classes, now link to the feature. Before, they matched nothing. - New marker.
ghk:trace feature=<path>links any file to a feature explicitly.
- Aggregate. The aggregate name and its class (
ghk graph --serve [--port N](4.9). The traceability graph in the browser: features, scenarios, commands, events, endpoints, files and tests in columns, with search; clicking a node traces it. The graph is rebuilt on every reload. Like the Web Studio, it is bound to 127.0.0.1, protected by a session token and an exact Host check, and disabled in CI. The page loads nothing external.- IR cache (4.8). The semantic model is a pure function of the feature, its file name, the options and the CLI version.
- In memory. A
generaterun builds it once per feature, instead of once per preset, lint rule and domain model. - On disk.
graphand the kernel refresh ofghk upgradecache it across runs in.ghe/cache/ir. - Not cached. Builds that depend on the constitution, an existing code base or an LLM.
- In memory. A
GHK_DECLARE_TOPOLOGY=false. It skips creating the broker topology at start-up in every backend, for least-privilege identities when infrastructure as code owns the topology.- Database TLS from
DATABASE_URL. Every runtime honours libpq'ssslmode(require,verify-ca,verify-full) andsslrootcertin the URL.- Fixed in the runtimes. The JVM (runtime, Spring and Quarkus) and .NET used to drop the query string, Elixir and PHP ignored it, Rust's
sqlxwas built without TLS, and node-postgres treatedrequireasverify-full, which rejects the managed databases' private CAs. - Terraform. The generated
DATABASE_URLends in?sslmode=require, anddb_require_tlsis now on by default, so the database refuses unencrypted connections. - Golden check.
golden-build.js --db-tlsruns the integration suites and the image smoke test against a PostgreSQL that only accepts TLS.
- Fixed in the runtimes. The JVM (runtime, Spring and Quarkus) and .NET used to drop the query string, Elixir and PHP ignored it, Rust's
amqps://for PHP. The Laravel runtime connects to RabbitMQ over TLS (Amazon MQ, CloudAMQP) through php-amqplib's connection factory. The other runtimes already took TLS from the URL.- Apache Kafka broker adapter (4.1;
stack.messaging: "kafka"). The JVM (Spring Java and Kotlin, Quarkus), TypeScript, .NET, Python and Go runtime kernels get a Kafka adapter behind the same ports as the other brokers. MySQL and MongoDB persistence are planned for 3.3.- Clients. The official ones:
kafka-clients(version from the Spring Boot or Quarkus BOM), Confluent's@confluentinc/kafka-javascript,Confluent.Kafkaandconfluent-kafka; Go uses franz-go, which needs no cgo, so the production image stays static. - Mapping. The exchange and the DLX are topics; the queue and the DLQ are consumer groups on them. Publish waits for every in-sync replica (
acks=all, idempotent producer); ack commits the offset; a message that is neither acked nor dead-lettered is read again. - Configuration.
KAFKA_BOOTSTRAP_SERVERS, and for managed clustersKAFKA_SECURITY_PROTOCOL,KAFKA_SASL_MECHANISM(PLAIN, SCRAM-SHA-256, SCRAM-SHA-512),KAFKA_SASL_USERNAMEandKAFKA_SASL_PASSWORD.GHK_BROKER=kafkaselects it at run time. - Local runs.
docker-compose.ymlstarts a single-node KRaft Kafka (apache/kafka); before,messaging: kafkastarted an unconfiguredcp-kafkacontainer. - Deployment. On AWS, Google Cloud and Azure the service connects to an existing cluster (MSK, Managed Service for Apache Kafka, the Event Hubs Kafka endpoint, Confluent Cloud):
kafka_bootstrap_servers,kafka_sasl_usernameandkafka_sasl_passwordare inputs stored in the secret manager, and no Amazon MQ, Pub/Sub or Service Bus resources are created. The service creates its own topics. - Other runtimes. Rust, Ruby, Elixir and PHP keep RabbitMQ with
stack.messaging: "kafka". - Goldens.
java-kafka,quarkus-kafka,nestjs-kafka,dotnet-kafka,fastapi-kafkaandgo-kafkarun IT1–IT7 against a single-node broker;terraform-aws-kafka,terraform-gcp-kafkaandterraform-azure-kafkavalidate the deployment.
- Clients. The official ones:
- Broker adapters for the Go, Rust, Ruby, Elixir and PHP runtime kernels.
- Pub/Sub in all five. REST with no client library (Go
net/http, Rustreqwest, RubyNet::HTTP, Elixir:httpc, PHPext-curl), behind the same ports and run-time selection as the other stacks. - Service Bus in Go only.
runtime/servicebus_broker.gousesazservicebusandazidentity, and is generated only withstack.messaging: "servicebus". - No Service Bus for Rust, Ruby, Elixir and PHP. They have no official SDK. On Azure, use self-managed RabbitMQ or CloudAMQP (
AMQP_URL). Withstack.messaging: "servicebus", RabbitMQ stays the default broker. - Inbox. The consumers poll the subscription and dead-letter through the adapter. IT1–IT7 run through the ports.
- Goldens.
go-pubsub,go-servicebus,rust-pubsub,rails-pubsub,phoenix-pubsubandlaravel-pubsub.
- Pub/Sub in all five. REST with no client library (Go
- Pub/Sub and Service Bus adapters for the .NET and Python runtime kernels.
- .NET.
Runtime/Brokers.csandRuntime/ServiceBusBroker.cs, with Azure.Messaging.ServiceBus and Azure.Identity. - Python.
app/runtime/broker.pyandservicebus_broker.py, with azure-servicebus and azure-identity. - Service Bus is opt-in. It is generated only with
stack.messaging: "servicebus". - Goldens.
dotnet-pubsub,dotnet-servicebus,fastapi-pubsubandfastapi-servicebus.
- .NET.
- Pub/Sub and Service Bus adapters for the TypeScript runtime kernel (NestJS, Express; goldens
nestjs-pubsubandnestjs-servicebus).- Same contract as the JVM.
runtime/broker.tshas the ports, RabbitMQ and Pub/Sub (REST overfetch), and run-time selection. - Service Bus.
runtime/servicebus-broker.tsuses@azure/service-busand@azure/identity, and is generated only withstack.messaging: "servicebus". - Inbox. The consumer now polls the subscription (
start()/drain()), so it works the same on every broker.
- Same contract as the JVM.
- Azure Service Bus adapter for the JVM runtime kernel (opt-in with
stack.messaging: "servicebus", goldenquarkus-servicebus).- SDK. It uses the official Azure SDK (
azure-sdk-bom), with the JDK HTTP transport instead of Netty. - Auth. Microsoft Entra ID through
SERVICEBUS_NAMESPACE(managed identity), or a connection string. - Verification. IT1–IT7 pass against the official emulator (SQL Edge plus fixed entities). The service harness can now mount files, wait on a log line and start services in order.
- AWS. It is covered by Amazon MQ for RabbitMQ with the existing adapter.
- SDK. It uses the official Azure SDK (
- Broker adapters in the JVM runtime kernel (Spring Java and Kotlin, Quarkus): RabbitMQ and Google Cloud Pub/Sub (golden
quarkus-pubsub).- Ports. The outbox relay and the inbox consumer use broker-neutral ports (
EventPublisher,EventSubscription,Broker). - Selection at run time.
GHK_BROKERpicks the broker; otherwise the configured variables decide.stack.messaging: "pubsub"sets the default. One image can run on any cloud. - Pub/Sub adapter. It uses the REST API with no client library: it authenticates through the metadata server (workload identity) or
GOOGLE_OAUTH_ACCESS_TOKEN, publish waits for Pub/Sub to accept the message, and the consumer dead-letters failed messages to the DLX topic. - Tests. IT1–IT7 now go through the adapters and pass against both RabbitMQ and the Pub/Sub emulator.
- Harness. Extra services (
src/core/services.ts) accept a start command and a readiness probe.
- Ports. The outbox relay and the inbox consumer use broker-neutral ports (
- Production container image for every backend.
ghk generatewrites aDockerfileand.dockerignore.- Image. The build is multi-stage and the image runs as a non-root user. It is configured only with environment variables, so one image runs on ECS, Cloud Run, Container Apps and Kubernetes.
- Health. NestJS and Spring (Java and Kotlin) get
/healthand/health/ready, which checks PostgreSQL. Each stack's probe paths are inresolveHealth. - Verification. Golden builds now build each image, start it next to PostgreSQL and RabbitMQ, and require both probes to answer 200;
--no-imageskips this. - Docs. See
docs/DEPLOYMENT.md.
- Kotlin + Quarkus 3.40 LTS backend (4.6, golden
kotlin-quarkus). Select it withstack.language: "kotlin"andstack.framework: "quarkus"(also offered byghk init). It is built with Gradle and the Quarkus plugin, and combines the Kotlin domain kernel and Cucumber steps of the Kotlin Spring stack with the Java runtime kernel and the Quarkus application layer of the Java Quarkus stack. Micronaut remains a candidate for a later release. - Java + Quarkus 3.40 LTS backend (golden
quarkus). Select it withstack.framework: "quarkus".- Shared kernel. It uses the same domain kernel, Cucumber runner and runtime kernel (PostgreSQL + RabbitMQ + OpenTelemetry, IT1–IT7) as Spring.
- Application layer. It has the same HTTP contract as Spring: a Quarkus REST resource and the HS256 JWT tenant filter (tenant only from the claim). The Agroal pool is configured from
DATABASE_URLthrough a config source. The outbox relay runs on the Quarkus scheduler, and SmallRye Health serves/q/health/live|ready. - Build and tests. Maven on Java 21, with Dev Services off. A
@QuarkusTestHTTP integration test runs under-Pintegration. - Versions. They are pinned in
generators/versions.ts. The OpenTelemetry BOMs (stable and alpha) are imported before the Quarkus BOM.
- Industry profiles (
industry.id). There are 8 reference-standard profiles plusgeneric: banking (BIAN, ISO 20022), telecom (TM Forum ODA, SID), manufacturing (RAMI 4.0, AAS, ISA-95), health (HL7 FHIR, openEHR), supply chain (SCOR-DS, GS1), insurance (ACORD), aviation (IATA NDC, ONE Order) and automotive (AUTOSAR, ISO 26262). Seedocs/INDUSTRIES.md.- Lint.
ghk lint,convergeand the MCPlint_specificationtool run the profile rules (GHK101–GHK803) plus GHK090, which limits capability depth to L4.industry.disabledRulesskips rules. - Agents. The IR gets
mustcompliance constraints. Theghk implementprompt (compact with-C) and the agent prompts get an Industry Standards section..ghe/industry-context.mdand.jsonare written, with their schema inschemas/industry-context.schema.json. - Contracts. OpenAPI and AsyncAPI carry
info.x-industry, and the ADR gets an Industry Standards section. - Firewall. The industry's sensitive paths (PHI, payments, OTA, …) require human approval.
- CLI. New
ghk industry list|show|apply,ghk init --industry(also asked interactively, and it preselects the recommended architecture), and the MCP toolget_industry_profile. - Opt-in only. A legacy
domainProfilesuch aspaymentsdoes not turn on an industry;ghk upgradesuggestsghk industry apply banking.
- Lint.
Changed
- Spring Boot 4.1 (Java and Kotlin). Spring Boot 3.x lost open-source support on 2026-06-30.
- Versions. Generated Spring projects use Spring Boot 4.1.1 (Spring Framework 7, Jakarta EE 11, JUnit 6), the
spring-boot-starter-webmvcstarter, Kotlin 2.3.21 and Gradle 8.14. - Jackson. The runtime kernel, shared with Quarkus, keeps Jackson 2 (
jackson-databindandjackson-datatype-jsr310, now declared explicitly). Spring itself uses Jackson 3. - HTTP test. It reads
local.server.port, because@LocalServerPortmoved. - Existing services. Code you added on Spring Boot 3 may need the Spring Boot 4 migration steps: starters, test autoconfiguration packages, and Jackson 3.
- Versions. Generated Spring projects use Spring Boot 4.1.1 (Spring Framework 7, Jakarta EE 11, JUnit 6), the
- Promoted to stable. No stack and no command is in beta any more.
- Stacks. Java + Quarkus and every Pub/Sub and Service Bus broker adapter. Each is built, tested and run against the official emulators by its golden build on every CI run.
- Commands.
risk,quality,graph,speckit,benchandweb. Their exit codes and--jsonoutput are covered by the CLI contract tests and kept across 3.x. ghk quality --json. New. It reportsgatePassed, thereasonsa human must approve, the risk card and the coverage result, and exits 4 when the gate fails. Before,--jsongave only{"ok": false}.
- Dependencies.
ip-address10.7.4 (through@modelcontextprotocol/sdk; GHSA-rxp7-6hxx-x8q5). For development, vitest 4.1.12 and vite 8.3.5 (GHSA-qxg6-89mg-rqv8, GHSA-xp26-3454-mjgp, and the vite and launch-editor advisories).npm auditreports no vulnerabilities. - The CLI's own CI and release workflows use
actions/checkout@v7andactions/setup-node@v7, like the pipelines it generates. - Source layout (4.11). The command definitions moved from
src/index.tstosrc/cli/, one module per group ofdocs/COMMANDS.md, andghk --helplists the commands in those groups. The IR extractors moved fromsrc/core/ir-builder.tstosrc/core/ir/. The IR is unchanged: it was compared with the previous build for 35 features.
Fixed
- Java/Kotlin frameworks without a preset (
ktoroffered byghk init,micronaut, ...) no longer generate Spring Boot code silently. They are reported as experimental and get contracts and prompts only.stack-detectorrecognises Quarkus, Micronaut and Ktor builds. - The following were found by regenerating and probing the reference projects (
ghk-test-projects) with 3.2.0.OpenAPI matches the generated API.
openapi.jsondescribes the route every generated backend serves,POST /api/v1/<feature>/{id}/{command}:commandis an enum of the feature's commands;- the
Idempotency-Keyandtraceparentheaders are documented; - the body is the command payload;
- the responses are 202, 200, 401, 409 and 422, with
CommandResultandErrorschemas.
Before, it listed verb-style paths that the service never served (
POST /api/v1/<feature>,PUT …/{id}, …), wrapped the body inrequestId,timestampandpayload, and copied HTTP codes from the scenarios.<feature>is the@aggregatetag or the feature name without accents. Spanish features used to get paths such as/api/v1/ejecuci-n-de-pagos-...-.ghk validateand features without events. It no longer fails (exit 4) on the AsyncAPI document thatgeneratewrites for a feature with no events. An emptychannelsobject is valid AsyncAPI 2.x, so it is now a warning.Broker configuration. With
stack.messaging: "pubsub",docker-compose.ymlruns the Pub/Sub emulator and passes its variables to the app. Before, it started RabbitMQ under the namepubsub..env.exampleand the Dockerfile header list the selected broker's variables.Enterprise constitution.
ghk init --enterprisefills.gherkin-ai/constitution.yamlfrom the answers: architecture, stack, broker, JWT auth, and the industry's compliance frameworks. It used to write a fixed NestJS/AWS template. The.gitignorenow keeps the constitution in version control and ignores the rest of.gherkin-ai/(credentials and logs).PHP topology names. The Laravel runtime named its exchange and queues after the feature, not the service, unlike every other runtime. In a multi-feature service its topology therefore differed from the other stacks and from the generated infrastructure.
OpenTelemetry configuration.
- Spring always exported over gRPC to
localhost:4317and ignoredOTEL_EXPORTER_OTLP_ENDPOINT. - Quarkus always exported to
localhost:4318, with noservice.name. - The .NET OpenTelemetry setup was never called.
- Spring always exported over gRPC to
ghk initgate workflow. It usedactions/checkout@v4and Node.js 20, which reached end of life in April 2026. It now uses the current actions and Node.js 24.Rust services with several features. The runtime command service applied only the last generated feature. The other features' routes answered 422 "unknown aggregate type". The new production image smoke test found it.
QA agent prompt. Existing step definitions are listed by their project-relative path. Before, regenerating wrote the machine's absolute paths (such as
/home/<user>/...) into the committedprompts/qa-agent.md.Step definitions dictionary. The QA and AI engineer prompts no longer list the BDD step skeletons gherkin-ai wrote on the previous run (their checksum still matches
.ghe/inventory.json); edited step files are listed again. Before, a secondghk generatewrote different prompts than a clean one. Java and Kotlin steps were also listed twice.
ghk createwith the Spanish CLI language. The guided, quick and headless modes wrote Spanish keywords (Característica:,Escenario:) without the# language: esheader, so the feature did not parse andghk lintscored it 0. They now write the header. Headless mode no longer depends on the machine's CLI language: it writes English unless the JSON sets"language": "es".- Existing projects are never overwritten.
ghk initreplaced an existinggherkin-ai.config.jsonand.ghkgovernance.yamlwithout asking. It now refuses (exit 2) unless--force..ghkgovernance.yamlwas rewritten from the configuration on everyghk generate. It now carries a checksum of its content: an unedited policy is refreshed, an edited one is kept and the new version goes to.ghkgovernance.yaml.ghk-new.ghk addwrote a TypeScript contract and Jest stubs in every stack, with emptyit()bodies that passed, and overwrote its files on each run. It now writes TypeScript files only for TypeScript and JavaScript projects, withit.todotests, uses the.ghk-newprotection ofgenerate, and needs--targetoutside NestJS.ghk upgradenever prunes its files, nor anything outsideoutputDir.ghk detectsetoutputDirto the existing application (./src,./app,./lib); it now uses./generated-specs.
ghk verify --servicesworks for every generated backend. It started only PostgreSQL and RabbitMQ, ran in the project root instead ofoutputDir, and its read-only sandbox could not install dependencies, so it failed for most services.- It starts the broker of
stack.messagingwith the golden builds' recipes, now insrc/core/services.ts: the Pub/Sub emulator, the Service Bus emulator with its database, or a single-node Kafka. - The toolchain's commands run in
outputDir;-candtestCommandstill run whereverifyis called. - Every toolchain mounts its dependency caches as named volumes (
ghk-cache-<name>), writable under the strict sandbox and shared with the golden builds. - The integration suite runs in the toolchain profile, like the golden builds: the image's disposable root and default capabilities, with the limits and
no-new-privileges.verify --dockerkeeps the strict profile. - Convergence after the tests.
verifyranghk convergewith a fixed 80% threshold after every passing run, and exited 4 ("CI/CD Gate Failed") when the specification was below it, although the tests had passed. It now reports the score in one line, and gates on it only with--converge-threshold <score>, exiting 7 likeghk converge. - A failed run prints the last lines of its output.
sandbox.servicesacceptscommand,ready,readyLogandfiles.--isolated, which wrote its own compose file with older images, is a deprecated alias of--services.
- It starts the broker of
- Lint. GHK009 did not count rejected, failed, expired, declined or refused outcomes (nor
rechazado,vencido,falla) as error paths. GHK007 reported "service", which is business vocabulary in TM Forum SID, IATA ONE Order and many domains. ghk detectalso recognizes.csprojfiles in subdirectories and their database provider (PostgreSQL unless only SQL Server is referenced), Elixir and Phoenix (LiveView as its frontend), andbuild.gradle.kts. It defaults Go to chi, the generated framework, instead of gin.ghk skillMCP entries used the absolute path of the local installation; they are now the pinnednpx -y gherkin-ai@<version> mcpentry ofghk mcp install.ghk skillrules. The rules written to.cursorrules,.windsurfrulesand.github/copilot-instructions.mdtold agents to runghk constitution, which does not exist, and to readgenerated-specs/contracts.ts, which is not generated. They now name only existing commands and paths: the firewall scope,lint --explain-ir,implement,.ghk-newhandling,converge,riskand the industry context.
Documentation
- New guides.
docs/ADOPTION.md(adding gherkin-ai to an existing code base: adoption levels, configuration, gates to tighten, agents, generation next to existing code, roles and a rollout checklist) anddocs/MIGRATION-3.2.md(from 3.1, and the path from 3.0 and 2.x). docs/INDUSTRIES.md. Each profile now lists its standards with their scope, the lint rules with their severity, the vocabulary, the recommended architecture and patterns, the compliance reminders, the human-approval paths, the rules given to agents, and a sample feature that passes its rules.- Brought up to date with 3.2. README (industry standards, brokers, deployment), ARCHITECTURE (module layout, golden steps), COMMANDS (
industry,lint --explain-ir,init --industry), ENTERPRISE (Spring Boot 4.1 and Quarkus in the stack table, brokers, OTLP), RUNTIME-KERNEL (broker adapters), DEPLOYMENT (Kafka variables), MCP_GUIDE (get_industry_profile), and the step indexer, IDE skills and headless mode pages.
[3.1.1] - 2026-10-13
Fixed
- Windows (git
core.autocrlf): generated files checked out with CRLF line endings no longer count as edited. Before,ghk generatewrote.ghk-newinstead of updating them, andghk upgradekept stale files instead of removing them. Checksums are now compared ignoring line endings. - Phoenix LiveView with several features: each feature has its own LiveView route,
/<feature>, and the first feature is also served at/. Before, the last generated feature replaced the others at/.
[3.1.0] - 2026-10-13
Generated backends become services you can keep, from the 3.0.0 field reviews. The generated output changes: see docs/MIGRATION-3.1.md.
Added
- Application layer wired to the runtime kernel (all 12 backends).
- Contract.
POST /api/v1/<feature>/{id}/{command}runs the command through the kernel'sCommandService: idempotency key, outbox,traceparent. It returns 202 created, 200 replayed, 409 in progress, or 422 for a domain error. - Tenant. It comes only from a validated HS256 bearer token (
JWT_SECRET; claim from the newsecurity.tenantClaim, defaulttenant_id).X-Tenant-Idis never trusted and there is no default tenant: requests without one get 401. - Outbox relay worker. It runs in-process for NestJS, Express, Spring, ASP.NET Core, FastAPI, Go, Phoenix and Axum, and as
manage.py outbox_relay,artisan outbox:relayandrails outbox:relayelsewhere. - Spring. It gets
application.propertiesand aDataSourcebuilt fromDATABASE_URL. - Tests. Each backend has unit tests of the contract with a fake command port, and an HTTP integration test against PostgreSQL.
- Contract.
- Multi-feature services.
- Contracts. Each feature owns
contracts/<feature>/(openapi.json,asyncapi.json, ADR). The rootopenapi.jsonandasyncapi.jsonare the union of every feature's contracts. - Kernel registry. The runtime command service handles every generated aggregate, with a new
aggregateTyperequest field. - Service-wide files. Routes, the NestJS
AppModule, .NETProgram.cs, the Python domain package, the Rust domain module, the Prisma schema (one model per feature), the Behat contexts and the frontend entry cover every generated feature. - Frontends. The entry mounts every feature's panel:
- Vue:
main.ts. - React:
main.tsx, with a store that registers every slice and takes one client per feature (createAppStore({ <feature>: client })). - Angular: a new
AppComponent. Each feature gets its own<feature>-client.token.ts(replacingclient.token.ts), and the realtime service routes pushed events byaggregateType. - Next.js:
app/page.tsx. - React Native:
App.tsx. - Flutter:
main.dart, with one tab per feature.
- Vue:
- Topology. The RabbitMQ topology is named after the service (
<service>.events). - Golden builds generate and test a two-feature service for every backend and frontend.
- Contracts. Each feature owns
- Protection of implemented code.
generateoverwrites a file only if its checksum still matches what was generated; otherwise it writes<file>.ghk-new.- New options:
generation.protectglobs, the.ghk-implementedmarker,--forceand--dry-run. - Files without a recorded checksum are overwritten only if they carry the generated header.
- New options:
ghk upgrade --kernelrefreshes only the runtime kernel: it replaces unedited files and writes.ghk-newfor edited ones.--allcovers every project under the current directory;--dry-runonly reports.ghk verify --servicesruns the stack's integration suite in its toolchain container against PostgreSQL 17 and RabbitMQ 4.sandbox.servicesadds extra containers. The golden builds use the same module.ghk lint --all/ghk converge --allcheck every feature of every project in a monorepo and print one table (exit 4 / 7).- Traceability.
ghk graphalso follows@trace:<Symbol>scenario tags andghk:implements <Symbol>comments; scenarios carry their source line. generation.package/generation.groupIdset the JVM package and groupId and the .NET root namespace.- Lint rule GHK015 warns about command or aggregate names with digits, example data, or more than four words.
ghk implementlists the feature's commands, events, endpoints and scenarios, and writes one master prompt per feature.
Changed
- Names come from the domain, not from example data.
- Command subjects ignore quoted values, numbers and tables.
- Fields come from data-table headers, never from values or from verbs and prepositions before a quoted value.
- Prisma gets one model per aggregate.
lintandconvergewithout-fhonour the configuredspecDir.- Removed the disconnected 3.0 placeholders, and the now-unused
@nestjs/cqrs,@nestjs/schedule, MediatR, MassTransit and EF packages:- NestJS: CQRS, outbox, saga and idempotency modules, plus the
X-Tenant-Idmiddleware. - Java: CQRS, outbox, saga, idempotency and multitenancy classes.
- .NET: MediatR handlers, the MassTransit saga, the EF outbox and inbox, the EF Core OpenTelemetry instrumentation,
HttpHeaderTenantServiceand the Testcontainers mock. The kernel persists with Npgsql;stack.orm: entity-framework-corenow only guides your own code (docs/ENTERPRISE.md). - Django: the ORM outbox.
- Go and Python: the pattern packages.
- Every backend: the in-memory HTTP handlers.
- Cleanup:
ghk upgrade --pruneremoves these files from existing projects when they are unedited.
- NestJS: CQRS, outbox, saga and idempotency modules, plus the
Fixed
lintGHK002 now accepts a user-story actor line without an article, such as "Como cliente de la tienda".- The Spring OpenTelemetry bean no longer fails when a global OpenTelemetry is already registered (Java agent or tests).
- Shared domain types no longer collide when a service has several features: Kotlin, C# and Python
DomainValidationException, Go domain package, Rust domain module.
Security
- Generated projects pin OpenTelemetry releases without known advisories:
- .NET: 1.9.0 → 1.19.x. Fixes GHSA-4625-4j76-fww9 in the OTLP exporter and GHSA-g94r-2vxg-569j in
OpenTelemetry.Api. - Go:
otelv1.31.0 → v1.47.0. Fixes CVE-2026-24051, CVE-2026-39883, CVE-2026-81869 and CVE-2026-81870. The generatedgo.modand the Go toolchain image now require Go 1.26. - Java / Kotlin: BOM 1.43.0 → 1.67.0. Fixes CVE-2026-45292.
Telemetry.javano longer overrides the deprecatedTextMapGetter.keys. - Rust: 0.31 → 0.33. Fixes CVE-2026-48504.
- Node: the floor of
@opentelemetry/coreandsdk-trace-baseis now^2.12.0. Fixes CVE-2026-54285.
- .NET: 1.9.0 → 1.19.x. Fixes GHSA-4625-4j76-fww9 in the OTLP exporter and GHSA-g94r-2vxg-569j in
[3.0.1] - 2026-10-09
Bug-fix release from the 3.0.0 field reviews (an LMS of 7 services and a 9-feature NestJS/Vue project). No change to the generated output contract; ghk upgrade is not required.
Fixed
implementcrash and lost checksums.generateand the audit trail wrote two different formats to.ghe/inventory.json. The file is now{version: '2', artifacts, executions}:- both old formats are still read;
generatemerges artifacts across features instead of replacing them;- the audit trail only touches executions, so
upgrade --prunekeeps working afterimplement.
convergeas a gate. Scores now track real evidence:- Coverage: JaCoCo totals come from the report-level counters (not the first method).
lcov.infois read, and Cobertura attributes are read in any order. An unrecognised report no longer stops the search. With no report the dimension showsn/aand is left out of the average instead of counting as 0.coverageTargetis read from the project config. - Architecture: layers are found at any depth: Maven/Gradle packages,
internal/,.NETX.Domainprojects and common aliases such asadaptersandapi. - Specification Quality: uses the lint score, so it no longer repeats Scenario Completeness.
- Traceability: events asserted in
Thensteps count as tested.
- Coverage: JaCoCo totals come from the report-level counters (not the first method).
- Scenario categories:
- a scenario carries every category that applies, for example authorization and error-handling;
- authorization also recognises roles, permissions, 401/403 and access denied;
- a logged-in success still counts as the happy path.
ghk quality: JaCoCo CSV totals are summed over every line, and the Go coverage total is parsed.lint:- GHK006 and GHK007 ignore quoted example values such as
"MATH-101"; - acronyms mentioned in the feature description count as defined;
- GHK006 reports each term once per feature;
- a missing or unparseable file fails the run (exit 4, also with
--json); - the average only counts files that were linted.
- GHK006 and GHK007 ignore quoted example values such as
validate:- prohibited framework imports are checked only in domain/application code, not in infrastructure, controllers, Nest modules or
main.ts; node_modules,dist,targetand.gitare skipped;- AsyncAPI auto-detection prefers the feature's own document;
--targetis registered.
- prohibited framework imports are checked only in domain/application code, not in infrastructure, controllers, Nest modules or
verify: an unset container limit keeps its default instead of producing--network undefined.- Locale:
- the project's
locale(andGHK_LOCALE) takes precedence over the global choice; - validator messages and the
addprompt are translated instead of mixing Spanish and English.
- the project's
- Local environment:
.env.exampleanddocker-compose.ymluse each stack's own variables and port (Spring, .NET, Python, Go, Rails, Phoenix, …);- both always provide
DATABASE_URLandAMQP_URLfor the runtime kernel; - RabbitMQ gets a dev user, because
guestis localhost-only; - the Serverless runtime is
nodejs22.x.
- Gherkin: scenarios inside
Rule:blocks are parsed (with the Rule's tags), andBackgroundsteps get step definitions and run first in every generated scenario.
[3.0.0] - 2026-10-05
Enterprise-readiness release, driven by the reviews of 2.6.x. Contains breaking changes: see docs/MIGRATION-3.0.md. For operators: docs/ENTERPRISE.md. Support and versioning policy: SUPPORT.md.
Added
- Runtime kernel for every backend:
- What it is. A verified path for persistence, messaging and tracing (
docs/RUNTIME-KERNEL.md):- a PostgreSQL command service with idempotency claims and a transactional outbox;
- an outbox relay with
FOR UPDATE SKIP LOCKEDleases and publisher confirms; - an inbox consumer with deduplication and a dead-letter queue;
- a saga orchestrator with reverse compensation;
- W3C trace context across the command, publish and consume spans.
- Where. Implemented with each language's standard driver, AMQP client and OpenTelemetry SDK: NestJS, Express, ASP.NET Core, Spring Boot (Java, Kotlin), FastAPI, Django, Go, Laravel, Rails, Phoenix and Axum.
- Verification. The integration suite (IT1–IT7) runs in every backend golden build against PostgreSQL 17 and RabbitMQ 4.
- What it is. A verified path for persistence, messaging and tracing (
- OpenTelemetry in the frontends: the generated API clients (React, Vue, Angular, Next.js, React Native, Flutter) send a
traceparentheader, and their generated tests assert it. - Agent firewall:
- What it decides. One decision point for agent writes, commands, network access, secrets and MCP tools: ALLOW, REQUIRE_APPROVAL or DENY.
- Policy sources. Built-in rules,
policy.firewall,.ghkgovernance.yamland the impact scope of the feature being implemented. - Where it applies. The MCP server,
verify --auto-fix --applyandautopilot --apply(blocked files become proposals), andghk firewall check|policy|hook, including a Claude CodePreToolUsehook. - Self-protection. Agents cannot edit
.ghkgovernance.yaml.
- Delivery risk (
ghk risk):- Input. The git change set, an explicit file list or the working tree.
- Scoring. LOW to CRITICAL across six weighted dimensions, each with evidence: security, business criticality, change radius, test weakness, contract drift and architecture drift.
- Policy and CI.
policy.risk.requireApprovalAtandpolicy.risk.criticalPathsconfigure approval;--fail-ongates CI with exit code 4.
- Traceability graph (
ghk graph):- What it links. Feature → scenario → command / event / endpoint, connected to the files and tests that reference them.
- Output. A summary, JSON, Mermaid or DOT;
--tracefor one symbol and--scopefor a feature's change scope.
- GitHub Spec Kit interop:
ghk speckit import(spec.md → .feature) andghk speckit export, round-tripping user stories, priorities and FR-### requirements. - A/B benchmark harness (
ghk bench):- What it compares. The same agent on the same task, with and without gherkin-ai.
- Scoring. Deterministic: build, tests, hidden acceptance tests (copied in after the agent finishes), convergence, files changed and time.
- Cost. No LLM is called by the harness itself.
- Hardened Docker sandbox for
verify --docker:- no network by default (
--docker-network); - memory, CPU and process limits;
- all capabilities dropped,
no-new-privilegesand a read-only root filesystem; - the stack's verified toolchain image;
- configurable in
sandbox.*.
- no network by default (
- AWS CDK infrastructure is opt-in (
infrastructure.awsCdk, default on for SQS/SNS messaging). The generated app (EKS with IRSA, DLQ alarm) has its own golden build with CDK assertions andcdk synth. convergemeasures generated contracts: OpenAPI operations and status codes, AsyncAPI events, and domain types in the generated sources. Each dimension reports its basis (artifacts,specificationorreports).SUPPORT.md(semver contract and support windows) and issue templates.- Layered, validated configuration: defaults → organization (
GHK_ORG_CONFIG) → user → project → environment, validated with zod; organizationlockedpaths; published JSON Schema (schemas/config.schema.json);ghk config show|validate|schema. - LLM providers: Azure OpenAI (API key or Entra ID), Amazon Bedrock, Google Gemini and Vertex AI, OpenAI-compatible gateways (
llm.baseUrl+llm.headers), alongside OpenAI, Anthropic and Ollama. Per-request timeouts, a single retry layer honoringRetry-After, per-run token budgets, and allow-lists for providers, models and endpoints. - Corporate networking:
HTTPS_PROXY/NO_PROXYandnetwork.proxyfor all providers; extra trusted CAs vianetwork.caFile. - Credentials: OS keychain storage (
ghk login,--api-key-stdin),ghk logout,ghk auth status. - Automation contract: documented exit codes (2 usage, 3 config, 4 gate, 5 policy, 6 provider, 7 drift);
--jsonprints exactly one JSON document on stdout for every command;--quiet;NO_COLOR. - Audit and telemetry: structured
audit.jsonlandtelemetry.jsonl(local only) with execution ids; LLM calls, MCP calls, agent write decisions and plugin loads are audited;ghk audit export --format jsonl|csv --since. - Agent write guards:
autopilotis dry-run by default (--apply);--applyis refused in CI (--allow-unattended-writes) and on protected branches (--force-branch). - Governed plugins:
plugins.loadwith an organization allow-list (plugins.allow). - Every stack is stable: 13 backends (NestJS, Express, ASP.NET Core, Spring Boot Java and Kotlin, FastAPI, Django, Go, Laravel 13, Rails 8, Phoenix, Axum, Flutter), 7 frontends (React, Vue, Angular 22, Next.js 16, React Native/Expo 57, Flutter, Phoenix LiveView) and gRPC/GraphQL contracts. CI generates each one and builds it and runs its generated tests in the stack's official Docker image (
scripts/golden-build.js);ghk stackslists them. - Shared domain kernel: every stack renders the same aggregate, unit tests, HTTP contract test and pending BDD steps bound to the feature file.
- Opt-in gRPC and GraphQL contracts (
contracts.grpc,contracts.graphql), validated with buf and graphql-js. - Web Studio works offline: Tailwind and Font Awesome are bundled instead of loaded from a CDN; Playwright end-to-end tests assert that no external request is made.
- CI/release: OS × Node 22/24 matrix, blocking
npm audit, golden builds, CLI contract tests against the built binary, and a release workflow with npm provenance and a CycloneDX SBOM. --thresholdforlintandconverge.ghk upgrade: assisted upgrade of 2.x projects.- Reports what the project needs: generated-file versions, config, CI scripts, MCP clients and legacy credential files.
- With
--apply, regenerates on a new git branch and removes stale generated files only when they were never edited. --checkgates CI.
- NestJS 12 and Prisma 7 (opt-in):
- New config keys
stack.frameworkVersion("11"default,"12") andstack.ormVersion("6"default,"7"), also settable withghk init --frameworkVersion/--ormVersion. - NestJS 12 projects are generated as ES modules.
- Prisma 7 projects use the
prisma-clientgenerator,prisma.config.tsand the driver adapter for the configured database. - All four NestJS combinations and Express with Prisma 7 have their own golden build.
- New config keys
@aggregate:Namefeature tag sets the type name used by every generator, instead of the name derived from a long feature title.
Changed
- Startup time reduced from about 0.7 s to about 0.15 s: command handlers and networking are loaded lazily.
- MCP server rebuilt on
@modelcontextprotocol/sdk:- Read-only by default; write tools need
mcp.allowWrite, and destructive tools also needGHK_ALLOW_DESTRUCTIVE. - Central path containment, agent policy and auditing on every call.
- Command output is captured instead of corrupting the stdio protocol.
- Commands are invoked in-process, so the server works when installed globally.
ghk mcp installpins the package version.
- Read-only by default; write tools need
- Web Studio: per-session token, exact Host and Origin checks, path containment, no shell execution.
- Security patterns unified in
src/core/security. Secrets are redacted from LLM prompts, log files and audit records. - Logger: levels, stderr for diagnostics, opt-in rotated log file; no longer writes
.ghe/logsinto the working directory on every run. - Single version source: the CLI banner,
--versionand the MCPserverInfoall read the version frompackage.json. The MCP server previously reported a hardcoded value. - Package contents:
CHANGELOG.md,LICENSE,SECURITY.mdandschemas/are now published. - Generated NestJS and Express projects use current dependencies:
- NestJS 11, Express 5, Prisma 6.19, Zod 4 (
z.uuid(),z.email(),z.iso.datetime()), Jest 30, Cucumber 13, TypeScript 6 (module: nodenext),@types/node22. - Step definitions load through
tsxinstead of the unmaintainedts-node. - Tenant scoping moved from the removed Prisma
$usemiddleware to a client extension (PrismaService.tenant). The generated repository uses it. - NestJS 12 and Prisma 7 are opt-in (see Added). NestJS 11 and Prisma 6 stay the defaults.
- NestJS 11, Express 5, Prisma 6.19, Zod 4 (
- TypeScript projects without a NestJS or Express backend:
- A frontend framework in
stack.framework(react,vue,angular,nextjs,react-native) generates that stable frontend project. - Other backends (
fastify,node-native) generate contracts and prompts only, and are reported as experimental. - Previously both got a Playwright spec containing only comments.
nestis accepted as an alias ofnestjs.
- A frontend framework in
Fixed
autopilot --applyskipped the CI and protected-branch guards. It imported the write guard but never called it, and did not pass--allow-unattended-writes/--force-branchon to its verify step..ghkgovernance.yamlallowedPathswas never enforced. Only protected paths were checked. The glob matcher also accepted any path containing the pattern text.- Documentation: the architecture page listed MCP tools that do not exist; the README listed container images the CLI does not use; the evaluation report was a self-scored rubric. They were replaced by documents that match the code and by reproducible evidence (
docs/EVALUATION_REPORT.md). - Credential leak between providers: a key belonging to another provider could be sent to the selected one (for example, the OpenAI key sent to Anthropic).
--apiKeywas silently ignored. - NestJS idempotency race: expired or failed keys could be re-claimed by two concurrent requests.
- Generated NestJS projects did not compile:
- inconsistent
PrismaServicepaths; - missing dependencies;
- escaped
\ninside step definitions; - missing Prisma models;
- wrong Prisma delegate casing.
- inconsistent
- Generated .NET projects did not compile:
- non-existent
Microsoft.EntityFrameworkCore.PostgreSQLpackage; - invalid root namespace for hyphenated project names;
- Aspire AppHost compiled into the API project;
- wrong command namespaces;
- missing event record;
- missing OpenTelemetry, Testcontainers, ServiceDiscovery and Swashbuckle packages.
- non-existent
- Unhandled async errors:
program.parse()→parseAsync(). - Help and workspace detection: workspace detection no longer prompts or changes directory for
--helpor in CI.--projectno longer creates directories (except forinit). - Web Studio path traversal:
/api/features/*and/api/filewere affected (sibling-prefix bypass). - Portability:
verifyno longer shells out tosleep, which is not available on Windows. - Dependency vulnerabilities: resolved transitive advisories (brace-expansion, fast-uri, hono, ip-address).
Fixed (generation)
- Localized features (
# language: esor any leading comment) were parsed as Markdown, producing names likeLanguageEs. - Identifiers kept broken fragments of accented words (
CreaciN); one-letter words were glued to the next (yrenderizado). - Decimal amounts before a quoted value produced invalid field types (
00DTO). - Connection URLs without credentials (
amqp://rabbitmq:5672) were rejected as leaked secrets. - Generators derived the feature's type names differently, so .NET handlers referenced commands and read models the contracts never declared; all generators now share one naming helper.
- Features outside
outputDirwere not found by the generated test runners; they are now copied into<outputDir>/features/. - Go contracts imported
uuidwithout using it when a feature declared no events (go vetfailure). - Prisma schemas redeclared
id/tenantIdwhen the feature mentioned anIDvalue. - Ruby and Elixir step definitions double-escaped
/and|, breaking steps that contain URL paths; Go dropped backticks from step patterns.
Removed
- Node.js 20 support (end-of-life); the CLI requires Node.js 22.12 or later.
- Superseded frontend generators (
react-generator,vue-pinia-generator,angular-ngrx-generator,angular-signalr-service) and the classic NgRx store mode. ghk login --apiKey/--token/--user/--endpoint/--serverand theauthalias oflogin.- MCP tool
run_cli_login;clearonrun_cli_audit. - Legacy hook manager
src/core/hooks.ts. - Stray development files from the repository root (
cdk-test-out.ts,scratch/,specs/, pack logs).
[2.6.5] - 2026-09-28
Published to npm without a changelog entry; reconstructed from git history.
Added
- Kotlin contract generation integrated with the contract generation system.
- Markdown EARS parser (
src/core/parsers/markdown-ears-parser.ts). - Plugin management in
ghk generate. - AWS CDK infrastructure stack (SNS, SQS, DynamoDB, EKS, Secrets Manager).
- Multi-tenancy support for Go, Java, Python and NestJS generators; Prisma multi-tenancy and relation tracking.
- OpenTelemetry Jaeger exporter and additional instrumentations.
ghk auditHTML report generation.- Coverage analysis in
ghk qualityand--isolatedmode inghk verify.
Changed
- NestJS Outbox and Saga infrastructure with atomic claims and idempotency patterns.
- API keys are no longer persisted in
auth.json; Row-Level Security enforcement and governance checks for destructive MCP operations. - Deprecation warnings for manual prompt workflows.
[2.6.4] - 2026-09-16
Fixed
- README explicitly included in the npm bundle.
Docs
- Multi-stack evaluation report (
docs/EVALUATION_REPORT.md) and updated command documentation.
2.6.3 (2026-09-15)
Bug Fixes
- correct package.json files array to ensure npm registry parses README.md (78f34fa)
[2.6.2] - 2026-09-15
Added
- Docker Validation Script (
validate.sh): C# and .NET generators now emit avalidate.shscript to verify compilation cleanly inside an isolated Docker container without relying on host SDKs. - Git Commit Suggester:
ghk generatenow intelligently outputs a draft commit message in.ghe/suggested_commit.mddocumenting the scaffolds, features generated, and CI validations. - Atomic Concurrency Handlers (C#): Replaced in-memory Idempotency and Outbox implementations with robust PostgreSQL atomic locks (
FOR UPDATE SKIP LOCKEDandTryAddAsync).
Changed
- BDD Framework Migration: Replaced deprecated
SpecFlow.xUnitwithReqnroll.xUnitas the standard BDD C# framework for generated step definitions. - Improved C# Scaffolding: Cleaned up stubs (
Task.CompletedTask) and replaced them with functional Entity Framework Core snippets (ApplicationDbContext, DbSets) and explicit Scaffolding exceptions to pass the internal Anti-Stub Guardrail. - Dynamic Brokers:
preset-csharp-dotnet.tsnow injectsMassTransitconfiguration (RabbitMQ vs SQS) dynamically based ongherkin-ai.config.jsoninstead of hardcoding. - Docker Compose Security: Database passwords are no longer hardcoded in
docker-compose.yml; the generator now uses shell variables (${POSTGRES_PASSWORD:-dev_password}).
Fixed
- CS0111 Step Duplication: C# Step Definitions generator now uses a
Setto prevent duplicate method generation when scenarios share the same BDD steps. - MediatR Contract Constraints: Fixed
IRequestinheritance bounds for Commands and Queries in C# contracts to satisfy MediatRIRequestHandlertype constraints. - AWS CDK Naming Bug: Fixed PascalCase conversion for project names with hyphens (e.g.,
transactional-system->TransactionalSystemInfrastructureStack) to prevent invalid TS identifiers in CDK. - Artifact Sprawl: Forced default
outputDirin config to./to prevent split-brain architecture where.featurefiles live in the root and code lives inside a nestedgenerated-specsfolder. - TS Leak in C#: Prevented Node.js/Zod
contracts.tsfiles from being incorrectly emitted into C# project trees.
[2.6.1] - 2026-09-07
Fixed
- Added
@vitest/coverage-v8to devDependencies. - Migrated Vitest configuration to
vitest.config.mtsfor native ESM compatibility. - Updated local
publish:prodscript to remove--provenanceflag for CLI terminal execution.
[2.6.0] - 2026-09-07 - Official Enterprise Release
Added
- Semantic Intermediate Representation (IR Engine): Rich 37KB AST & NLP extractor (
src/core/ir-builder.ts) for state machines, domain events, invariants, and traceability. - Enterprise Constitution & Guardrails (
.gherkin-ai/): Full YAML governance schema (src/core/constitution.ts), agent role permissions, LLM policies, and compliance framework schemas. - Specification Linter (
ghk lint): 14 linting rules for Gherkin specifications with quality scoring and CLI diagnostic outputs. - Specification Convergence Engine (
ghk converge): 6-dimensional spec-to-code alignment verification system with CONVERGED / DIVERGED status badges. - OpenAPI Schema Validator (
src/core/openapi-validator.ts): Validates generated OpenAPI 3.0 specs against Gherkin endpoints. - Plugin Architecture (
src/core/plugin-system.ts): Extensible plugin interface for third-party generators and presets. - Impact Analysis (
ghk impact) & PR Reviewer (ghk pr-review): Blast radius analyzer and automated PR review bot. - Prisma Schema & Zod Generator (
src/generators/prisma-generator.ts): Auto-generatesschema.prismafrom IR entities and state machines, with conditionalnpx prisma formatexecution. - Failed Attempt Diagnostics Logging: Automatically logs raw prompts, responses, and diffs to
.gherkin-ai/logs/autopilot/pre-rollback on agent failures. - Supply Chain Security & Provenance: Published with npm
--provenanceand included GitHub Actions CI workflow generator.
Fixed
- Dynamic Spec Directory Resolver (
src/utils/spec-dir-resolver.ts): Fixed criticalENOENT: specs/bug by auto-resolvingfeatures/,specs/, orspecDirin configuration. - Non-Interactive CI Mode: Automatic directory suggestion/selection in headless mode without prompt locks.
- Clean Architecture Import Compliance: Removed
@nestjs/commonimports from step definition presets to guarantee 0 layer violations inghk validate.
[2.3.1] - 2026-09-02
Changed
- Promoted self-healing engine from beta to stable.
- Minor performance patches.
[2.2.0] - 2026-08-15
Added
- Web Studio UI (
ghk web) for visual orchestrating. - AST Step Definitions Indexer for hallucination prevention via
ts-morph. - DOM & Data Model Anchor for precise test generation.
ghk skillcommand for IDE (.cursorrules) integration.- Headless CI/CD Mode.
- Official
@cucumber/gherkinparser support. - Initial multi-stack templates (Rust, Go, Mobile, React, Java).