Skip to content

Use with generated knowledge systems

adrkit and generated knowledge systems solve adjacent problems:

  • adrkit records why and governs change. Human-reviewed ADRs carry lifecycle state, typed relationships, and affects matchers that let CI and agents find the decisions governing a path.
  • Generated knowledge describes the system as it exists now. Tools such as OpenWiki can synthesize browsable architecture documentation and reconnect factual claims to source evidence as the implementation changes.

Use both layers when you want generated current-state documentation without giving generated content authority over human decisions.

Artifact Owns Written by
docs/adr/** Ratified intent, alternatives, lifecycle, typed relationships, and what a decision affects People and agents through the repository’s normal pull-request review
Source and tests Current implementation and executable behavior The product development workflow
openwiki/INSTRUCTIONS.md Human-reviewed instructions that constrain the generated projection People and agents through a separate pull request
Other Markdown plus OpenWiki claims and manifest JSON under openwiki/** Generated explanations, claims, and current-state architecture projections OpenWiki through its own update workflow
OpenWiki-managed blocks in AGENTS.md and CLAUDE.md Pointers that help coding agents discover the generated wiki OpenWiki within its documented marker boundaries

An OpenWiki page may cite an ADR and explain it. It must not accept, reject, deprecate, supersede, or rewrite that ADR. When implementation and an accepted record disagree, preserve both facts and route the discrepancy to people.

Run the adrkit governing-decisions Action on source pull requests. It resolves the accepted records that govern changed files and comments on the pull request where the change is being reviewed:

name: ADR governing decisions
on:
pull_request:
permissions:
contents: read
pull-requests: write
jobs:
governing-decisions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mbeacom/adrkit/packages/ci@v0

Configure OpenWiki updates independently, using its current automation guide. Keep generated documentation under openwiki/**, allow only OpenWiki’s managed blocks in AGENTS.md and CLAUDE.md, and keep model credentials and update failures out of the adrkit job. An OpenWiki update may open a documentation pull request after source changes land; it should not become a prerequisite for adrkit’s deterministic pull-request context.

Preserve the explicit add-paths allowlist from OpenWiki’s reference GitHub workflow. Do not copy its credential persistence unchanged for this boundary. GitHub permissions apply to a whole job, not one step, so run generation and publication in separate jobs. The generator receives a read-only token and no persisted git credential. A fresh publisher job receives the write credential only after the protected-path guard succeeds.

Save the workflow as .github/workflows/openwiki-update.yml. Before enabling it, configure:

  • repository variable OPENWIKI_MODEL_ID;
  • repository secret OPENAI_API_KEY for the OpenAI example below, or the provider-specific credential documented by OpenWiki; and
  • repository secret OPENWIKI_PR_TOKEN, containing a fine-grained token with contents:write and pull-requests:write.
name: OpenWiki update
on:
workflow_dispatch:
schedule:
- cron: '0 8 * * *'
# The ambient token is read-only. OPENWIKI_PR_TOKEN is a fine-grained token with
# contents:write and pull-requests:write, stored as a repository secret and
# passed only to the final action.
permissions:
contents: read
concurrency:
group: openwiki-update-${{ github.repository }}
cancel-in-progress: false
jobs:
generate:
runs-on: ubuntu-latest
steps:
- name: Check out without generator write credentials
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '22'
- name: Build the reviewed OpenWiki source revision
shell: bash
run: |
source_dir="$RUNNER_TEMP/openwiki-source"
git init "$source_dir"
git -C "$source_dir" remote add origin https://github.com/langchain-ai/openwiki.git
git -C "$source_dir" fetch --depth=1 origin c666f4262e4340e5675fa9804bb342b87bf87f1a
git -C "$source_dir" checkout --detach FETCH_HEAD
corepack enable
(
cd "$source_dir"
pnpm install --frozen-lockfile
pnpm run build
)
# This example uses OpenAI. Substitute the provider-specific environment
# documented by OpenWiki when you use another provider.
- name: Run OpenWiki
run: |
: "${OPENWIKI_MODEL_ID:?Set repository variable OPENWIKI_MODEL_ID}"
: "${OPENAI_API_KEY:?Set repository secret OPENAI_API_KEY}"
node "$RUNNER_TEMP/openwiki-source/dist/cli/cli.js" code --update --print
env:
OPENWIKI_PROVIDER: openai
OPENWIKI_MODEL_ID: ${{ vars.OPENWIKI_MODEL_ID }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Remove transient run state
run: rm -f -- openwiki/.run.json
# Comparing with GITHUB_SHA catches staged, unstaged, and locally committed
# changes. The second check catches new untracked protected files.
- name: Protect human-reviewed integration controls
shell: bash
run: |
protected=(
docs/adr
openwiki/INSTRUCTIONS.md
AGENTS.md
CLAUDE.md
.github/CODEOWNERS
.github/workflows/openwiki-update.yml
)
if ! git diff --exit-code "$GITHUB_SHA" -- "${protected[@]}"; then
echo 'OpenWiki modified tracked protected paths; refusing publication.' >&2
exit 1
fi
untracked="$(git ls-files --others -- "${protected[@]}")"
if [[ -n "$untracked" ]]; then
printf 'OpenWiki created protected paths:\n%s\n' "$untracked" >&2
exit 1
fi
# Archive only generated output. The user-authored brief was already
# proven unchanged and is excluded from the handoff.
- name: Package generated output
shell: bash
run: |
if [[ ! -d openwiki || -L openwiki ]]; then
echo 'OpenWiki output root must be a real directory.' >&2
exit 1
fi
invalid=()
while IFS= read -r -d '' path; do
invalid+=("$path")
done < <(find openwiki -mindepth 1 ! -type f ! -type d -print0)
while IFS= read -r -d '' path; do
case "$path" in
openwiki/INSTRUCTIONS.md | openwiki/*.md) ;;
openwiki/.claims/*.json | openwiki/.last-update.json | openwiki/.page-manifest.json) ;;
*) invalid+=("$path") ;;
esac
done < <(find openwiki -type f -print0)
while IFS= read -r -d '' path; do
invalid+=("$path")
done < <(find openwiki -type f -perm /111 -print0)
if (( ${#invalid[@]} )); then
printf 'OpenWiki created unsupported or executable output:\n' >&2
printf ' %q\n' "${invalid[@]}" >&2
exit 1
fi
tar \
--exclude='openwiki/INSTRUCTIONS.md' \
--exclude='openwiki/.run.json' \
-czf "$RUNNER_TEMP/openwiki-output.tgz" \
openwiki
- name: Upload generated output
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: openwiki-${{ github.run_id }}
path: ${{ runner.temp }}/openwiki-output.tgz
if-no-files-found: error
publish:
needs: generate
runs-on: ubuntu-latest
steps:
- name: Check out a fresh publishing workspace
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- name: Download generated output
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: openwiki-${{ github.run_id }}
path: ${{ runner.temp }}/openwiki-artifact
- name: Replace generated files while preserving the brief
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/openwiki-candidate"
tar -xzf "$RUNNER_TEMP/openwiki-artifact/openwiki-output.tgz" \
-C "$RUNNER_TEMP/openwiki-candidate"
rsync -a --no-links --delete --exclude '/INSTRUCTIONS.md' \
"$RUNNER_TEMP/openwiki-candidate/openwiki/" openwiki/
- name: Create OpenWiki update pull request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
with:
token: ${{ secrets.OPENWIKI_PR_TOKEN }}
add-paths: |
openwiki
branch: openwiki/update
commit-message: 'docs: update OpenWiki'
title: 'docs: update OpenWiki'
body: |
Automated OpenWiki documentation update.
Keep this pull request in draft until a reviewer confirms that ADR
lifecycle states, applicability, relationships, and source links
agree with the cited decision records.
draft: always-true
signoff: true

Unlike the upstream reference workflow, this stricter adaptation does not publish partial output: a failed OpenWiki run stops before artifact handoff and PR creation. At minimum, enable GitHub Actions failure notifications and compare the workflow’s last successful run with its expected schedule. A green adrkit check means the decision corpus and governing-decision resolution succeeded—it does not mean the generated wiki is current.

Treat openwiki/update as automation-owned. Do not push reviewer fixup commits to it; change the source, brief, or workflow on the default branch and rerun the update instead.

Add guidance like the following to the repository’s openwiki/INSTRUCTIONS.md:

# Decision records
Treat `docs/adr/**` as read-only normative decision evidence.
- Never create, edit, delete, accept, reject, deprecate, or supersede an ADR.
- Preserve each record's id and link to the original file.
- Present `accepted` records as ratified decisions. Call one governing for a
target only when `adr check` or `adr explain` reports it through a matching
`affects` declaration or inbound `@adr` marker; do not reimplement resolution.
- Present `draft` and `proposed` records as under review, not as current policy.
- Keep `rejected`, `superseded`, and `deprecated` records in decision history.
- Preserve `scope`, `affects`, and marker provenance where the consuming
contract exposes them. Label `supersedes`, `supersededBy`, `relatesTo`, and
`conflictsWith` relationships explicitly.
- Label every ADR-derived page as a non-authoritative generated projection and
record the source ADR-corpus git revision.
- When code differs from an accepted ADR, report the mismatch for human review.
Do not revise the ADR or infer a new decision from implementation alone.
- Treat machine verification of generated content as documentation provenance,
not as human ratification of a decision.

This brief lets OpenWiki use the corpus as evidence while preserving the distinctions that make the corpus useful to review and retrieval.

Enforce the write boundary outside the prompt

Section titled “Enforce the write boundary outside the prompt”

openwiki/INSTRUCTIONS.md is guidance to the documentation agent, not a repository permission boundary. Pair it with controls the generated workflow cannot reinterpret:

  1. Keep scheduled update commits limited to non-executable Markdown, JSON below openwiki/.claims/, and OpenWiki’s two root JSON manifests. Fail the run if openwiki/INSTRUCTIONS.md changes. Establish changes to that brief, AGENTS.md, CLAUDE.md, and the workflow in a separate human-reviewed pull request.
  2. Add docs/adr/**, openwiki/INSTRUCTIONS.md, AGENTS.md, CLAUDE.md, and the OpenWiki workflow to CODEOWNERS.
  3. Where a distinct reviewer is available, configure branch protection or a ruleset to require that review. CODEOWNERS alone requests review but does not make it mandatory. In a sole-maintainer repository, requiring the sole code owner to approve their own change deadlocks the normal path or leaves an administrator bypass as the routine escape; rely on credential isolation, the base-commit guard, and the committed-path allowlist as the hard automation boundary instead of claiming independent approval.
  4. Keep OpenWiki’s managed blocks in AGENTS.md and CLAUDE.md limited to pointers that help agents find the wiki. Review any change outside the documented markers as an ordinary source change.
  5. Open every generated-documentation pull request as a draft. Do not enable automatic merging; a reviewer must first compare ADR lifecycle, applicability, relationship, and source-link claims with the cited records.

For example:

# .github/CODEOWNERS
/docs/adr/ @your-architecture-reviewers
/openwiki/INSTRUCTIONS.md @your-architecture-reviewers
/AGENTS.md @your-architecture-reviewers
/CLAUDE.md @your-architecture-reviewers
/.github/workflows/openwiki-update.yml @your-architecture-reviewers

These controls keep an instruction-following failure from becoming a decision lifecycle change.

OKF v0.2 defines document lifecycle states such as draft, stable, and deprecated, plus machine- and human-verification events. These describe the knowledge document. adrkit’s accepted, rejected, and superseded states describe the outcome and history of a decision.

Do not map:

  • adrkit accepted to OKF stable as proof that a decision was ratified;
  • OpenWiki machine verified to adrkit provenance.ratifiedBy; or
  • a stale generated Claim to a violated or superseded ADR.

A source change means evidence needs another look. It proves a violation only when an applicable deterministic assertion actually evaluates and fails.

  1. A source pull request changes files.
  2. adrkit reports the accepted decisions governing those files on that pull request.
  3. People review the source change against those decisions.
  4. After merge, OpenWiki refreshes the generated description and its source evidence in a separate update.
  5. If the implementation and decision no longer agree, people either correct the implementation or propose a new ADR that explicitly supersedes the old decision.

If a generated-documentation change reaches a protected path or misrepresents an ADR’s lifecycle, applicability, relationship, or source:

  1. Disable the update workflow before its next scheduled run.
  2. Open a human-reviewed revert pull request that restores any protected paths and generated claims to their last reviewed state, and verify .github/CODEOWNERS was not weakened. Do not hide the event by rewriting shared history.
  3. Run adr lint and adr check against the restored corpus and affected source paths.
  4. Review generated-documentation pull requests since the last known-good run for the same boundary crossing.
  5. Correct the brief or output grammar that admitted the breach, regenerate from the last reviewed source revision, and confirm the branch-protection or ruleset configuration still enforces its intended review policy before re-enabling automation.

The same boundary applies to other generated knowledge systems: consume and project the decision corpus, but leave decision authority in its reviewed git history.