Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
200 lines
10 KiB
YAML
200 lines
10 KiB
YAML
name: CI Agent Skills Drift
|
|
|
|
# When a PR changes the app-development surface (twenty-sdk, create-twenty-app,
|
|
# twenty-client-sdk, or the shared manifest types), an agent checks whether the
|
|
# canonical skill content under packages/twenty-agent-skills is impacted and,
|
|
# only when it is, posts a single sticky comment with its findings.
|
|
#
|
|
# This is the skills counterpart to ci-app-docs-drift.yaml: the same source
|
|
# changes that stale the docs also stale the guidance agents follow.
|
|
|
|
on:
|
|
pull_request:
|
|
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
changed-files-check:
|
|
uses: ./.github/workflows/changed-files.yaml
|
|
with:
|
|
files: |
|
|
packages/twenty-sdk/**
|
|
packages/create-twenty-app/**
|
|
packages/twenty-client-sdk/**
|
|
packages/twenty-shared/src/application/**
|
|
packages/twenty-shared/src/types/**
|
|
|
|
agent-skills-drift-check:
|
|
needs: changed-files-check
|
|
# Secrets are unavailable on fork PRs; skip there and on bot PRs.
|
|
if: >-
|
|
needs.changed-files-check.outputs.any_changed == 'true' &&
|
|
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
github.event.pull_request.user.type != 'Bot'
|
|
timeout-minutes: 30
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
id-token: write
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Run agent skills drift agent
|
|
id: drift-agent
|
|
uses: anthropics/claude-code-action@ac7e24bf2938964b8ab203e417a2773802392ddd # v1.0.146
|
|
with:
|
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
claude_args: |
|
|
--max-turns 60 --json-schema '{"type":"object","properties":{"hasDrift":{"type":"boolean"},"summary":{"type":"string"}},"required":["hasDrift","summary"]}' --allowedTools "Bash(git diff *),Bash(git log *),Bash(git show *),Bash(grep *),Bash(cat *),Bash(ls *),Bash(find *),Bash(head *),Bash(tail *),Bash(gh pr comment *)"
|
|
prompt: |
|
|
You are the agent-skills drift checker for the twenty repository.
|
|
|
|
A pull request changed files in the app-development platform. Your job is to
|
|
decide whether the skill guidance under `packages/twenty-agent-skills/`
|
|
is impacted, and report your findings as ONE pull request comment.
|
|
|
|
These skills tell coding agents how to build Twenty apps. When they go stale
|
|
an agent confidently runs a command that no longer exists, so wrong guidance
|
|
is worse here than a missing doc page.
|
|
|
|
## Canonical source only
|
|
|
|
`packages/twenty-agent-skills/skills/` and
|
|
`packages/twenty-agent-skills/references/` are the canonical content.
|
|
|
|
`packages/twenty-agent-skills/dist/` is generated for distribution and is
|
|
not committed to main. Report the canonical file that needs an edit.
|
|
|
|
## Step 1 — Understand the change
|
|
|
|
The PR branch is checked out with full history; the base branch is
|
|
`origin/${{ github.base_ref }}`. Inspect what the PR changes however you
|
|
see fit. Only these kinds of changes are skill-relevant:
|
|
|
|
- CLI commands, subcommands, flags, defaults, or help text
|
|
(`packages/twenty-sdk/src/cli/commands/**`)
|
|
- `define*` function signatures, config properties, validation rules,
|
|
or their warnings (`packages/twenty-sdk/src/sdk/define/**`)
|
|
- Enum / string-union values and manifest types
|
|
(`packages/twenty-shared/src/application/**`, `packages/twenty-shared/src/types/**`)
|
|
- Exports added/removed/renamed in the `exports` maps of `twenty-sdk` or
|
|
`twenty-client-sdk` package.json, or in their public entry points
|
|
- Front-component runtime hooks and host API
|
|
(`packages/twenty-sdk/src/sdk/front-component/**`)
|
|
- The scaffold template (`packages/create-twenty-app/src/constants/template/**`)
|
|
and scaffolder flags/prompts (`packages/create-twenty-app/src/cli.ts`,
|
|
`create-app.command.ts`)
|
|
- Environment variables injected into logic functions or front components
|
|
- Error codes surfaced to app developers
|
|
- Default ports and instance URLs used during development
|
|
|
|
Internal refactors, tests, and implementation-only changes are NOT relevant —
|
|
if the changes contain only those, say so and stop.
|
|
|
|
## Step 2 — Map to skill content
|
|
|
|
Use this mapping to know which files to check (read the actual files, all
|
|
paths relative to `packages/twenty-agent-skills/`):
|
|
|
|
| Source area | Skill content |
|
|
|---|---|
|
|
| CLI commands (`src/cli/commands`) | `references/manage-app/cli-and-sync.md`, `skills/manage-app/SKILL.md`, `references/concepts/operating-rules.md` |
|
|
| Scaffolder flags, prompts, template | `skills/create-app/SKILL.md`, `references/develop-app/app-structure.md` |
|
|
| `defineObject`/`defineField`/relations/indexes | `references/develop-app/data-model.md` |
|
|
| `defineApplication`/roles/install hooks/variables | `references/concepts/how-apps-work.md`, `references/publish-app/prepare-for-app-store.md` |
|
|
| Logic functions, triggers, connections, agents/skills | `references/develop-app/logic.md` |
|
|
| Workflows and their lifecycle | `references/develop-app/workflows.md` |
|
|
| Views, navigation, page layouts, command menu | `references/develop-app/layout.md`, `references/develop-app/standalone-pages.md` |
|
|
| Front components, SDK imports, runtime hooks | `references/develop-app/front-components.md`, `references/design/front-component-ui.md` |
|
|
| Test layout, test target ports | `references/develop-app/tests.md`, `references/concepts/operating-rules.md` |
|
|
| Publish/install/deploy, versioning | `references/publish-app/prepare-for-app-store.md`, `skills/publish-app/SKILL.md` |
|
|
| MCP endpoints, transport, auth | `references/use-twenty-mcp/setup.md`, `references/use-twenty-mcp/result-formatting.md` |
|
|
| Enum value sets (FieldType, ViewType, availabilityType, NavigationMenuItemType, ...) | the reference documenting that value set (search for the enum name) |
|
|
|
|
Two extra checks specific to this package:
|
|
|
|
- `scripts/validators/` encodes cross-document contracts as literal string
|
|
fragments (exact commands, ports, section headings). A renamed command or
|
|
changed port can make a validator assert something no longer true, so check
|
|
whether the change invalidates a fragment there.
|
|
- `references/concepts/operating-rules.md` is the single source of truth for
|
|
the durable rules and names exact commands. A command rename lands here.
|
|
|
|
Also check whether the PR already updates the impacted files — if it does,
|
|
verify the update matches the code change.
|
|
|
|
## Step 3 — Report
|
|
|
|
If there is NO skill impact, do NOT post or create any comment.
|
|
Skip the comment entirely and go straight to Step 4.
|
|
|
|
Only when the skills are impacted, post exactly one comment on PR
|
|
#${{ github.event.pull_request.number }} with:
|
|
`gh pr comment ${{ github.event.pull_request.number }} --edit-last --create-if-none --body ...`
|
|
(this updates the previous drift-check comment in place on subsequent runs).
|
|
Start the comment body with the marker `<!-- agent-skills-drift-check -->`.
|
|
|
|
Comment format:
|
|
- Title line: `### Agent skills drift check`
|
|
- A table with columns **Change** (what changed in the code),
|
|
**Skill file** (repo-relative path, canonical only), **Status**
|
|
(`✅ already updated in this PR` / `⚠️ needs update`), and **Suggested fix**
|
|
(one concrete sentence, e.g. the exact command to replace).
|
|
- When any row needs an update, end with one line reminding the author to run
|
|
`npx nx run twenty-agent-skills:validate` after editing the canonical content.
|
|
- Be terse. No preamble, no sign-off. Only report genuine drift — if unsure
|
|
whether something is user-facing, say it's uncertain rather than asserting.
|
|
|
|
## Step 4 — Return the verdict
|
|
|
|
After posting the comment, return your final answer as the structured
|
|
output the CI gate consumes:
|
|
- `hasDrift`: `true` if at least one impacted skill file still needs updating
|
|
(drift is NOT fully resolved by this PR); `false` if there is no skill
|
|
impact, or every impacted file is already correctly updated in this PR.
|
|
- `summary`: one terse sentence describing the verdict.
|
|
|
|
Environment: GH_TOKEN is available for `gh`. The PR branch is checked out.
|
|
settings: |
|
|
{
|
|
"env": {
|
|
"GH_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
|
}
|
|
}
|
|
|
|
- name: Gate on drift verdict
|
|
if: always()
|
|
env:
|
|
AGENT_OUTCOME: ${{ steps.drift-agent.outcome }}
|
|
STRUCTURED_OUTPUT: ${{ steps.drift-agent.outputs.structured_output }}
|
|
run: |
|
|
if [ "$AGENT_OUTCOME" != "success" ]; then
|
|
echo "::error::Agent skills drift checker did not complete (agent step outcome: $AGENT_OUTCOME)."
|
|
exit 1
|
|
fi
|
|
if [ -z "$STRUCTURED_OUTPUT" ]; then
|
|
echo "::error::Agent skills drift checker did not return a structured verdict."
|
|
exit 1
|
|
fi
|
|
has_drift=$(printf '%s' "$STRUCTURED_OUTPUT" | jq -r '.hasDrift')
|
|
if [ "$has_drift" = "true" ]; then
|
|
echo "::error::Agent skills drift detected. See the agent-skills-drift-check comment on this PR."
|
|
exit 1
|
|
fi
|
|
if [ "$has_drift" = "false" ]; then
|
|
echo "No agent skills drift."
|
|
exit 0
|
|
fi
|
|
echo "::error::Structured verdict present but 'hasDrift' was not a recognizable boolean: $has_drift"
|
|
exit 1
|