Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 8 additions & 3 deletions .github/aw/actions-lock.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
{
"entries": {
"actions/github-script@v9": {
"repo": "actions/github-script",
"version": "v9",
"sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3"
},
"actions/github-script@v9.0.0": {
"repo": "actions/github-script",
"version": "v9.0.0",
"sha": "d746ffe35508b1917358783b479e04febd2b8f71"
},
"github/gh-aw-actions/setup@v0.69.1": {
"github/gh-aw-actions/setup@v0.71.1": {
"repo": "github/gh-aw-actions/setup",
"version": "v0.69.1",
"sha": "b2d32ac2825a5c57cb99851c2ca00094d5e131a6"
"version": "v0.71.1",
"sha": "239aec45b78c8799417efdd5bc6d8cc036629ec1"
},
"github/gh-aw/actions/setup@v0.69.1": {
"repo": "github/gh-aw/actions/setup",
Expand Down
421 changes: 308 additions & 113 deletions .github/workflows/repo-assist.lock.yml

Large diffs are not rendered by default.

37 changes: 29 additions & 8 deletions .github/workflows/repo-assist.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ tools:
repo-memory: true

safe-outputs:
# GitHub App used to mint installation access tokens for safe-output
# operations (PR creation, branch pushes, issue/comment writes). Replaces
# the default GITHUB_TOKEN attribution so commits are attributed to the
# bot identity, and — critically — pushes from this token DO trigger
# downstream workflows like Lint PR and build, which GITHUB_TOKEN pushes
# do not. Requires APP_ID variable + APP_PRIVATE_KEY secret.
github-app:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
messages:
footer: "> Generated by 🌈 {workflow_name}, see [workflow run]({run_url}). [Learn more](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md)."
run-started: "{workflow_name} is processing {event_type}, see [workflow run]({run_url})..."
Expand All @@ -64,15 +73,25 @@ safe-outputs:
hide-older-comments: true
create-pull-request:
draft: true
title-prefix: "[Repo Assist] "
# No title-prefix here: PR titles must satisfy Conventional Commits
# (validated by .github/workflows/conventional-pr-title.yml). Bot PRs
# are identified by the `repo-assist` label and the `repo-assist/*`
# branch naming convention instead.
labels: [automation, repo-assist]
protected-files: fallback-to-issue
max: 4
# Push an extra empty commit under the App token so pull_request /
# pull_request_target workflows (Lint PR, build) actually fire on PRs
# created by the agent.
github-token-for-extra-empty-commit: app
push-to-pull-request-branch:
target: "*"
title-prefix: "[Repo Assist] "
# Restrict pushes to PRs the agent itself created — same identification
# as create-pull-request (label-based), since title-prefix is gone.
labels: [repo-assist]
max: 4
protected-files: fallback-to-issue
github-token-for-extra-empty-commit: app
create-issue:
title-prefix: "[Repo Assist] "
labels: [automation, repo-assist]
Expand Down Expand Up @@ -100,8 +119,8 @@ steps:
# Fetch open issues with labels (up to 500)
gh issue list --state open --limit 500 --json number,labels > /tmp/gh-aw/issues.json

# Fetch open PRs with titles (up to 200)
gh pr list --state open --limit 200 --json number,title > /tmp/gh-aw/prs.json
# Fetch open PRs with titles and labels (up to 200)
gh pr list --state open --limit 200 --json number,title,labels > /tmp/gh-aw/prs.json

# Compute task weights and select two tasks for this run
python3 - << 'EOF'
Expand All @@ -114,8 +133,10 @@ steps:

open_issues = len(issues)
unlabelled = sum(1 for i in issues if not i.get('labels'))
repo_assist_prs = sum(1 for p in prs if p['title'].startswith('[Repo Assist]'))
other_prs = sum(1 for p in prs if not p['title'].startswith('[Repo Assist]'))
def is_repo_assist(p):
return any(l.get('name') == 'repo-assist' for l in p.get('labels') or [])
repo_assist_prs = sum(1 for p in prs if is_repo_assist(p))
other_prs = sum(1 for p in prs if not is_repo_assist(p))

task_names = {
1: 'Issue Labelling',
Expand Down Expand Up @@ -307,14 +328,14 @@ Check memory for already-submitted ideas; do not re-propose them. Create a fresh

### Task 6: Maintain Repo Assist PRs

1. List all open PRs with the `[Repo Assist]` title prefix.
1. List all open PRs with the `repo-assist` label (e.g. `gh pr list --label repo-assist --state open`). PR titles follow Conventional Commits and no longer carry a `[Repo Assist]` prefix; the label and the `repo-assist/*` branch name are how you identify your own PRs.
2. For each PR: fix CI failures caused by your changes by pushing updates; resolve merge conflicts. If you've retried multiple times without success, comment and leave for human review.
3. Do not push updates for infrastructure-only failures — comment instead.
4. Update memory.

### Task 7: Stale PR Nudges

1. List open non-Repo-Assist PRs not updated in 14+ days.
1. List open PRs without the `repo-assist` label that haven't been updated in 14+ days (e.g. `gh pr list --state open --search "-label:repo-assist updated:<$(date -u -d '14 days ago' +%Y-%m-%d)"`).
2. For each (check memory — skip if already nudged): if the PR is waiting on the author, post a single polite comment asking if they need help or want to hand off. Do not comment if the PR is waiting on a maintainer.
3. **Maximum 3 nudges per run.** Update memory.

Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ Homepage = "https://fable.io"
[dependency-groups]
dev = [
"pytest>=9.0.3,<10",
"ruff>=0.15.10,<0.16",
"ruff>=0.15.11,<0.16",
"maturin>=1.13.1,<2",
"dunamai>=1.26.1,<2",
"pydantic>=2.13.0",
"pydantic>=2.13.3",
"attrs>=26.1.0",
"pyright>=1.1.408",
"ty>=0.0.30",
"ty>=0.0.32",
]

[tool.hatch.build.targets.sdist]
Expand Down
5 changes: 4 additions & 1 deletion src/fable-library-py/fable_library/reg_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ def _options_to_flags(options: int) -> int:
def create(pattern: str, options: int = 0) -> Pattern[str]:
# raw_pattern = pattern.encode("unicode_escape").decode("utf-8")
flags = _options_to_flags(options)
pattern = pattern.replace("?<", "?P<")
# Convert .NET named group syntax (?<name>...) to Python (?P<name>...).
# Only replace ?< when followed by a word character (name start), not by
# = or ! which are part of lookbehind assertions (?<=...) and (?<!...).
pattern = re.sub(r"\?<(?=[A-Za-z_])", "?P<", pattern)
return re.compile(pattern, flags=flags)


Expand Down
2 changes: 1 addition & 1 deletion tests/Python/Fable.Tests.Python.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</PackageReference>
<PackageReference Include="FSharp.UMX" Version="1.1.0" />
<PackageReference Include="Thoth.Json.Python" Version="0.5.1" />
<PackageReference Include="Fable.Python" Version="4.24.0" />
<PackageReference Include="Fable.Python" Version="5.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/Fable.Core/Fable.Core.fsproj" />
Expand Down
14 changes: 14 additions & 0 deletions tests/Python/TestRegex.fs
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,17 @@ let ``test doesn't succeed when not existing group without any named groups`` ()
let actual = r.Replace(text, replace)

actual |> equal expected

[<Fact>]
let ``test positive lookbehind works`` () =
let r = Regex @"(?<=A)\w+"
let text = "AB AC AD BD"
let ms = r.Matches(text) |> Seq.map (fun m -> m.Value) |> Seq.toList
ms |> equal [ "B"; "C"; "D" ]

[<Fact>]
let ``test negative lookbehind works`` () =
let r = Regex @"(?<!A)\d"
let text = "A1 B2 A3 C4"
let ms = r.Matches(text) |> Seq.map (fun m -> m.Value) |> Seq.toList
ms |> equal [ "2"; "4" ]
Loading