Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
151bdb8
Merge branch 'infra/11750-context-documentation' into infrastructure/…
eugene-manuilov Jan 2, 2026
59d8f2e
Expand Gemini context settings.
eugene-manuilov Jan 2, 2026
d1b7c91
Configure Gemini settings for MCP servers.
eugene-manuilov Jan 2, 2026
73030b5
Add `implement.toml` Gemini command.
eugene-manuilov Jan 2, 2026
412a038
Add GitHub Actions workflow to automate issue implementation via Gemi…
eugene-manuilov Jan 2, 2026
244a263
Add PHPUnit testing documentation and update Gemini settings to inclu…
eugene-manuilov Jan 2, 2026
b049e25
Remove unnecessary `--prompt` flag from Gemini CLI command.
Jan 6, 2026
7daa5b0
Pin `@google/gemini-cli` to version `0.22.5` in the Gemini workflow.
Jan 6, 2026
0bcda2e
Merge remote-tracking branch 'origin/develop' into infrastructure/114…
Jan 6, 2026
960ae91
Reformat Gemini workflow YAML indentation.
Jan 6, 2026
087f637
Merge remote-tracking branch 'origin/develop' into infrastructure/114…
Jan 7, 2026
4998b8a
Apply suggestions from code review
eugene-manuilov Jan 8, 2026
b72651b
Merge remote-tracking branch 'origin/develop' into gemini.
eugene-manuilov Jan 8, 2026
a4248f1
Address code review feedback.
eugene-manuilov Jan 8, 2026
83b1d73
Merge remote-tracking branch 'origin/develop' into infrastructure/114…
Jan 12, 2026
31f27c1
Update gemini version to 0.23.0.
Jan 12, 2026
585b7cf
Fix issues in context files and in the implement command.
Jan 12, 2026
56f7b2d
Update the github mcp settings to whitelist only issue reading tools.
Jan 12, 2026
c1a2f34
Merge remote-tracking branch 'origin/develop' into infrastructure/114…
Jan 14, 2026
873d47c
Replace @ escaping to use the back slash approach.
Jan 14, 2026
4255bc0
Update the gemini workflow to use a readonly token to read an issue.
Jan 14, 2026
f515e39
Update the implement command to enforce usage of tests.
Jan 14, 2026
19bf854
Merge remote-tracking branch 'origin/develop' into infrastructure/114…
eugene-manuilov Jan 15, 2026
d94350c
Refactor Gemini workflow to separate implementation and pull request …
eugene-manuilov Jan 15, 2026
04ee04d
Update Gemini workflow to use the default `GITHUB_TOKEN` secret inste…
eugene-manuilov Jan 15, 2026
c6b0c71
Switch Gemini GitHub tool configuration from an exclusion list to an …
Jan 15, 2026
1a22b2d
Update Gemini implement command configuration.
Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
649 changes: 649 additions & 0 deletions .gemini/commands/implement.toml

Large diffs are not rendered by default.

54 changes: 52 additions & 2 deletions .gemini/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
{
"contextFileName": "AGENTS.md"
}
"context": {
"fileName": [
"AGENTS.md",
"docs/context/js/component-conventions.md",
"docs/context/js/module-architecture.md",
"docs/context/js/widgets.md",
"docs/context/js/feature-tours.md",
"docs/context/js/jsdoc.md",
"docs/context/js/notifications.md",
"docs/context/js/tests.md",
"docs/context/js/utils.md",
"docs/context/js/state-management.md",
"docs/context/js/hooks.md",
"docs/context/js/storybook.md",
"docs/context/js/event-tracking.md",
"docs/context/js/feature-flags.md",
"docs/context/php/admin-features.md",
"docs/context/php/asset-management.md",
"docs/context/php/context-pattern.md",
"docs/context/php/dependency-injection.md",
"docs/context/php/module-architecture.md",
"docs/context/php/naming-conventions.md",
"docs/context/php/phpunit.md",
"docs/context/php/prompts-and-dismissals.md",
"docs/context/php/rest-api.md",
"docs/context/php/settings-management.md",
"docs/context/php/storage-patterns.md",
"docs/context/php/trait-composition.md"
]
},
"mcpServers": {
"github": {
"trust": false,
"httpUrl": "https://api.githubcopilot.com/mcp/?toolsets=issues",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
}
}
},
"tools": {
"exclude": [
"github__add_issue_comment",
"github__assign_copilot_to_issue",
"github__get_label",
"github__issue_write",
"github__list_issue_types",
"github__list_issues",
"github__search_issues",
"github__sub_issue_write"
]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we define this as an allowlist instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good idea, updated.

}
}
107 changes: 107 additions & 0 deletions .github/workflows/gemini.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Gemini Implement Issue

on:
workflow_dispatch:
inputs:
issue_number:
description: GitHub issue number to implement
required: true
type: number

jobs:
implement:
name: Implement Issue
runs-on: ubuntu-latest
timeout-minutes: 60
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems longer than reasonable. How long have we seen it take so far?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how much time it can take when we actually trigger it as a GitHub workflow. Let's have 60 for now and update once we see how it actually works.

permissions:
contents: write
issues: write
pull-requests: write
services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: wordpress
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
env:
DB_HOST: 127.0.0.1
DB_PORT: 3306
MYSQL_USER: root
MYSQL_PASSWORD: wordpress
MYSQL_DATABASE: wordpress_test
WP_VERSION: latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- name: Install SVN
run: sudo apt-get update && sudo apt-get install -y subversion
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
extensions: mysqli, runkit7, uopz
tools: composer:2.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get Composer Cache Directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Validate Composer configuration
run: composer validate --strict
- name: Install Composer dependencies
run: composer install --no-interaction --no-progress
- name: Install npm dependencies
run: npm ci -w assets -w storybook -w tests/js -w tests/e2e --include-workspace-root
- name: Set up WordPress test data
run: tests/phpunit/bin/install-wp-tests.sh "${MYSQL_DATABASE}" "${MYSQL_USER}" "${MYSQL_PASSWORD}" "${DB_HOST}":"${DB_PORT}" "${WP_VERSION}"
- name: Install Gemini CLI
run: |
npm install -g @google/[email protected]
gemini --version
- name: Run /implement command
run: |
gemini --yolo --model gemini-3-pro-preview "/implement ${{ inputs.issue_number }}"
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_READONLY_TOKEN }}
- name: Create Pull Request
id: create-pr
uses: peter-evans/create-pull-request@v7
with:
commit-message: 'Implement issue #${{ inputs.issue_number }}'
branch: gemini/issue-${{ inputs.issue_number }}
title: 'Implement #${{ inputs.issue_number }}'
body: |
🤖 Automated implementation of issue #${{ inputs.issue_number }}
Generated by Gemini CLI using the `/implement` command.
**Review checklist:**
- [ ] Code follows documented principles
- [ ] Tests pass locally
- [ ] Linting passes
- [ ] Manual testing completed
- [ ] Code review score ≥ 0.85
draft: true
- name: Comment on issue
if: steps.create-pr.outputs.pull-request-number
run: |
gh issue comment ${{ inputs.issue_number }} --body "🤖 Automated implementation created in PR #${{ steps.create-pr.outputs.pull-request-number }}
This is a draft PR generated by Gemini CLI. Please review the changes, run tests, and verify quality before marking ready for review."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
!.gemini/
.gemini/*
!.gemini/settings.json
!.gemini/commands/
!.gemini/commands/**
!.github
!.vscode
.vscode/*
Expand Down
6 changes: 3 additions & 3 deletions docs/context/js/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,10 @@ import { useSelect, useDispatch } from 'googlesitekit-data';
/**
* Custom hook description.
*
* @since 1.25.0
* \@since 1.25.0
*
* @param {string} parameter Description of parameter.
* @return {*} Description of return value.
* \@param {string} parameter Description of parameter.
* \@return {*} Description of return value.
*/
export default function useCustomHook(parameter) {
// Hook implementation
Expand Down
84 changes: 42 additions & 42 deletions docs/context/js/jsdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ All utility functions, hooks, and complex API functions should follow this patte
*
* [Brief description of function purpose]
*
* @since n.e.x.t
* \@since n.e.x.t
*
* @param {type} paramName Description of parameter.
* @param {type} [optionalParam] Description of optional parameter.
* @return {type} Description of return value.
* \@param {type} paramName Description of parameter.
* \@param {type} [optionalParam] Description of optional parameter.
* \@return {type} Description of return value.
*/
function myFunction( paramName, optionalParam = defaultValue ) {
// implementation
Expand All @@ -51,66 +51,66 @@ function myFunction( paramName, optionalParam = defaultValue ) {

### Required JSDoc Tags

#### @since Tag
#### \@since Tag
**Always required** - Documents when the feature was introduced, always use `n.e.x.t` value which will be replaced with the actual version later on.

```javascript
/**
* Returns a callback to activate a module.
*
* @since n.e.x.t
* \@since n.e.x.t
*
* @param {string} moduleSlug Module slug.
* @return {Function|null} Callback to activate module.
* \@param {string} moduleSlug Module slug.
* \@return {Function|null} Callback to activate module.
*/
```

#### @param Tag
#### \@param Tag
**Required for all parameters** - Documents parameter types and descriptions:

```javascript
// Basic parameter
@param {string} dateRange The date range slug.
\@param {string} dateRange The date range slug.

// Optional parameter with default
@param {boolean} [invertColor=false] Whether to reverse the +/- colors.
\@param {boolean} [invertColor=false] Whether to reverse the +/- colors.

// Complex object parameter
@param {Object} options Configuration options.
@param {string} options.baseName The base name to use.
@param {Function} options.controlCallback Callback function to issue the API request.
@param {Function} [options.validateParams] Optional validation function.
\@param {Object} options Configuration options.
\@param {string} options.baseName The base name to use.
\@param {Function} options.controlCallback Callback function to issue the API request.
\@param {Function} [options.validateParams] Optional validation function.
```

#### @return Tag
#### \@return Tag
**Required for functions that return values** - Documents return type and description:

```javascript
@return {Object} Partial store object with properties 'actions', 'controls', and 'reducer'.
@return {Function|null} Callback function or null if module doesn't exist.
@return {Array.<Object>} Array of widget objects.
\@return {Object} Partial store object with properties 'actions', 'controls', and 'reducer'.
\@return {Function|null} Callback function or null if module doesn't exist.
\@return {Array.<Object>} Array of widget objects.
```

### Complex Type Documentation

#### @typedef for Complex Data Structures
#### \@typedef for Complex Data Structures

Use `@typedef` to define complex object structures:
Use `\@typedef` to define complex object structures:

```javascript
/**
* Parse Analytics 4 report into data suitable for rendering.
*
* @typedef {Object} OverallPageMetricsData
* @property {string} metric Google Analytics metric identifier.
* @property {string} title Translated metric title.
* @property {Array.<Object>} sparkLineData Data for rendering the sparkline.
* @property {string} [datapointUnit] Optional datapoint unit, e.g. '%', 's'.
* @property {number} total Total count for the metric.
* @property {number} change Monthly change for the metric.
* \@typedef {Object} OverallPageMetricsData
* \@property {string} metric Google Analytics metric identifier.
* \@property {string} title Translated metric title.
* \@property {Array.<Object>} sparkLineData Data for rendering the sparkline.
* \@property {string} [datapointUnit] Optional datapoint unit, e.g. '%', 's'.
* \@property {number} total Total count for the metric.
* \@property {number} change Monthly change for the metric.
*
* @param {Object} report Raw Analytics report data.
* @return {OverallPageMetricsData} Processed metrics data.
* \@param {Object} report Raw Analytics report data.
* \@return {OverallPageMetricsData} Processed metrics data.
*/
function parseReportData( report ) {
// implementation
Expand All @@ -126,10 +126,10 @@ Custom hooks require comprehensive JSDoc documentation:
* Returns a callback to activate a module. If the call to activate the module
* fails, an error will be returned to the returned callback.
*
* @since n.e.x.t
* \@since n.e.x.t
*
* @param {string} moduleSlug Module slug.
* @return {Function|null} Callback to activate module, null if the module doesn't exist.
* \@param {string} moduleSlug Module slug.
* \@return {Function|null} Callback to activate module, null if the module doesn't exist.
*/
export default function useActivateModuleCallback( moduleSlug ) {
// hook implementation
Expand All @@ -145,15 +145,15 @@ Utility functions require detailed documentation with examples for complex cases
* Creates a store object implementing the necessary infrastructure for making
* asynchronous API requests and storing their data.
*
* @since n.e.x.t
* \@since n.e.x.t
*
* @param {Object} args Arguments for creating the fetch store.
* @param {string} args.baseName The base name to use for all actions.
* @param {Function} args.controlCallback Callback function to issue the API request.
* @param {Function} [args.reducerCallback] Optional reducer to modify state.
* @param {Function} [args.argsToParams] Function that reduces argument list to params.
* @param {Function} [args.validateParams] Function that validates params before request.
* @return {Object} Partial store object with properties 'actions', 'controls', and 'reducer'.
* \@param {Object} args Arguments for creating the fetch store.
* \@param {string} args.baseName The base name to use for all actions.
* \@param {Function} args.controlCallback Callback function to issue the API request.
* \@param {Function} [args.reducerCallback] Optional reducer to modify state.
* \@param {Function} [args.argsToParams] Function that reduces argument list to params.
* \@param {Function} [args.validateParams] Function that validates params before request.
* \@return {Object} Partial store object with properties 'actions', 'controls', and 'reducer'.
*/
export default function createFetchStore( {
baseName,
Expand Down Expand Up @@ -199,7 +199,7 @@ export default function createFetchStore( {
4. **Create typedefs** for complex recurring data structures

### Version Tracking
1. **Always include @since** for new functions and significant changes using `n.e.x.t` value
1. **Always include \@since** for new functions and significant changes using `n.e.x.t` value
3. **Document breaking changes** in function descriptions

### Consistency Rules
Expand Down
14 changes: 7 additions & 7 deletions docs/context/php/asset-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,14 +598,14 @@ interface Module_With_Assets {
/**
* Get assets to register for the module.
*
* @return Asset[] Array of Asset instances.
* \@return Asset[] Array of Asset instances.
*/
public function get_assets();

/**
* Enqueue all assets for the module.
*
* @param string $asset_context Context constant (Asset::CONTEXT_*).
* \@param string $asset_context Context constant (Asset::CONTEXT_*).
*/
public function enqueue_assets( $asset_context = Asset::CONTEXT_ADMIN_SITEKIT );
}
Expand Down Expand Up @@ -651,7 +651,7 @@ trait Module_With_Assets_Trait {
/**
* Set up module assets.
*
* @return Asset[] Array of Asset instances.
* \@return Asset[] Array of Asset instances.
*/
abstract protected function setup_assets();
}
Expand Down Expand Up @@ -688,8 +688,8 @@ interface Module_With_Inline_Data {
/**
* Get inline data for the module.
*
* @param array $modules_data Existing modules data.
* @return array Updated modules data with module's data added.
* \@param array $modules_data Existing modules data.
* \@return array Updated modules data with module's data added.
*/
public function get_inline_data( $modules_data );
}
Expand Down Expand Up @@ -901,8 +901,8 @@ final class Manifest {
/**
* Get manifest entry for asset handle.
*
* @param string $handle Asset handle.
* @return array [ $filename, $hash ] or [ null, null ] if not found.
* \@param string $handle Asset handle.
* \@return array [ $filename, $hash ] or [ null, null ] if not found.
*/
public static function get( $handle ) {
if ( null === self::$data ) {
Expand Down
Loading
Loading