-
Notifications
You must be signed in to change notification settings - Fork 4
release: workflow + main-scope agent fixes (v8.20.91) #286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
df07849
abef2d4
9be36e6
bcea744
cb86910
0ca9756
a921e85
d5d2a01
e4aa0a2
a29073b
837ab56
15b1705
1f761c2
48c3567
55b9b76
fb38cc5
263e8dd
b6ff43b
b6186ad
f14ccd5
6f1a657
2c3691f
1ad4b02
5d8dcf9
1e3b0e6
a31ad1f
ff352f9
a15ba0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 8.20.90 | ||
| 8.20.91 | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "enforcement": { | ||
| "blocking_enabled": true, | ||
| "main_scope_has_agent_privileges": false, | ||
| "workflow": { | ||
| "enabled": true, | ||
| "steps": [ | ||
| { "name": "Task", "tools": ["Task"] }, | ||
| { "name": "Plan", "tools": ["Plan"] }, | ||
| { "name": "Review Plan", "tools": ["Review"] }, | ||
| { "name": "Execute", "tools": ["Execute"] }, | ||
| { "name": "Review Execute", "tools": ["Review"] }, | ||
| { "name": "Document", "tools": ["Document", "Write", "Edit"] } | ||
| ] | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1 +1 @@ | ||||||
| 8.20.90 | ||||||
| 8.20.92 | ||||||
|
||||||
| 8.20.92 | |
| 8.20.91 |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -107,11 +107,30 @@ function main() { | |||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| const heredocMatch = firstLine.match(/<<-?\s*'?([A-Za-z0-9_:-]+)'?/); | ||||||
| const dashTrim = firstLine.includes('<<-'); | ||||||
| const heredocMatch = firstLine.match(/<<-?\s*(?:'([A-Za-z0-9_:-]+)'|"([A-Za-z0-9_:-]+)"|([A-Za-z0-9_:-]+))/); | ||||||
| if (heredocMatch) { | ||||||
| const terminator = heredocMatch[1]; | ||||||
| const terminatorRegex = new RegExp(`\\n${escapeRegex(terminator)}\\s*$`); | ||||||
| return terminatorRegex.test(trimmed); | ||||||
| const terminator = heredocMatch[1] || heredocMatch[2] || heredocMatch[3]; | ||||||
|
|
||||||
| // Require a quoted terminator OR a body with no command substitution | ||||||
| const leadingTabs = dashTrim ? '\\t*' : ''; | ||||||
| const terminatorRegex = new RegExp(`\\n${leadingTabs}${escapeRegex(terminator)}\\s*$`); | ||||||
| const hasTerminator = terminatorRegex.test(trimmed); | ||||||
| const isQuoted = Boolean(heredocMatch[1] || heredocMatch[2]); | ||||||
|
|
||||||
| if (!hasTerminator) { | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| if (!isQuoted) { | ||||||
| // Unquoted heredoc bodies perform substitution; ensure body is clean | ||||||
| const body = trimmed.replace(/^.*?\n/s, ''); | ||||||
|
||||||
| const body = trimmed.replace(/^.*?\n/s, ''); | |
| const body = trimmed.replace(/^.*?\n/, ''); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -965,7 +965,28 @@ To execute blocked operation: | |
|
|
||
| // CRITICAL: Check tool blacklist AFTER Bash coordination check | ||
| const blacklistResult = checkToolBlacklist(tool, toolInput, 'pm', projectRoot); | ||
| if (blacklistResult.blocked) { | ||
|
|
||
| // Docs fast-path: if markdown is already allowed via docs/ allowlist (including parent-path fast path), skip blacklist | ||
| let markdownAllowedFastPath = false; | ||
| if (filePath && filePath.endsWith('.md')) { | ||
| const markdownValidation = validateMarkdownOutsideAllowlist(filePath, projectRoot, false); | ||
| const outsideProject = path.relative(projectRoot, filePath).startsWith('..'); | ||
| const allowlistDirs = [ | ||
| getSetting('paths.story_path', 'stories'), | ||
| getSetting('paths.bug_path', 'bugs'), | ||
| getSetting('paths.memory_path', 'memory'), | ||
| getSetting('paths.docs_path', 'docs'), | ||
| 'agenttasks', | ||
| getSetting('paths.summaries_path', 'summaries') | ||
| ]; | ||
| const pathParts = path.normalize(filePath).split(path.sep); | ||
| const containsAllowlistedSegment = allowlistDirs.some((dir) => pathParts.includes(dir)); | ||
| const forceAllow = ALLOW_PARENT_ALLOWLIST_PATHS && outsideProject && containsAllowlistedSegment; | ||
|
|
||
| markdownAllowedFastPath = markdownValidation.allowed || forceAllow; | ||
| } | ||
|
Comment on lines
+969
to
+987
|
||
|
|
||
| if (blacklistResult.blocked && !markdownAllowedFastPath) { | ||
| log(`Tool blocked by blacklist: ${tool} (${blacklistResult.list})`); | ||
|
|
||
| const blockingEnabled = getBlockingEnabled(); | ||
|
|
@@ -1090,7 +1111,23 @@ To execute blocked operation: | |
| // Apply markdown validation if needed | ||
| if (shouldApplyMarkdownValidation) { | ||
| const markdownValidation = validateMarkdownOutsideAllowlist(filePath, projectRoot, false); | ||
| if (!markdownValidation.allowed) { | ||
|
|
||
| // If the file is outside the project, parent paths are allowed, and the path already contains an allowlisted segment, allow it | ||
| const allowParentPaths = ALLOW_PARENT_ALLOWLIST_PATHS; | ||
| const outsideProject = path.relative(projectRoot, filePath).startsWith('..'); | ||
| const pathParts = path.normalize(filePath).split(path.sep); | ||
| const allowlistDirs = [ | ||
| getSetting('paths.story_path', 'stories'), | ||
| getSetting('paths.bug_path', 'bugs'), | ||
| getSetting('paths.memory_path', 'memory'), | ||
| getSetting('paths.docs_path', 'docs'), | ||
| 'agenttasks', | ||
| getSetting('paths.summaries_path', 'summaries') | ||
| ]; | ||
| const containsAllowlistedSegment = allowlistDirs.some((dir) => pathParts.includes(dir)); | ||
| const forceAllow = allowParentPaths && outsideProject && containsAllowlistedSegment; | ||
|
|
||
| if (!markdownValidation.allowed && !forceAllow) { | ||
| log(`Markdown file outside allowlist blocked: ${filePath}`); | ||
|
|
||
| const blockingEnabled = getBlockingEnabled(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version mismatch in CHANGELOG: Entry shows
8.20.92but the PR title and rootVERSIONfile indicate this is release8.20.91. The8.20.92entry should either be renamed to8.20.91or moved to a separate PR if these are intended to be different releases.