snow-flow 10.0.78 → 10.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.78",
3
+ "version": "10.0.80",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -115,7 +115,7 @@ export namespace Agent {
115
115
  },
116
116
  review: {
117
117
  name: "review",
118
- description: "Code reuse review mode. Analyzes ServiceNow artifacts for reuse opportunities. Enterprise only.",
118
+ description: "Review mode. Analyzes ServiceNow artifacts for quality, security, coherence, and reuse opportunities. Enterprise only.",
119
119
  options: {},
120
120
  temperature: 0.3,
121
121
  color: "#a855f7",
@@ -132,6 +132,19 @@ export namespace Agent {
132
132
  websearch: "allow",
133
133
  codesearch: "allow",
134
134
  review_exit: "allow",
135
+ external_directory: {
136
+ [path.join(Global.Path.data, "reviews", "*")]: "allow",
137
+ },
138
+ edit: {
139
+ "*": "deny",
140
+ [path.join(".snow-code", "reviews", "*.md")]: "allow",
141
+ [path.relative(Instance.worktree, path.join(Global.Path.data, path.join("reviews", "*.md")))]: "allow",
142
+ },
143
+ write: {
144
+ "*": "deny",
145
+ [path.join(".snow-code", "reviews", "*.md")]: "allow",
146
+ [path.relative(Instance.worktree, path.join(Global.Path.data, path.join("reviews", "*.md")))]: "allow",
147
+ },
135
148
  }),
136
149
  user,
137
150
  ),
@@ -1,27 +1,51 @@
1
- You are the Code Reuse Reviewer Agent for Snow-Flow. Your role is to analyze ServiceNow artifacts created or modified during development activities and identify opportunities for code reuse and standardization.
1
+ You are the Review Agent for Snow-Flow. Your role is to analyze ServiceNow artifacts created or modified during development activities and provide comprehensive code review covering quality, security, coherence, DRY principles, and reuse of existing artifacts.
2
2
 
3
- IMPORTANT: You are in READ-ONLY analysis mode. You cannot and should not modify any code. Your role is purely analysis and feedback.
3
+ IMPORTANT: You are in READ-ONLY analysis mode. You cannot and should not modify any code. The ONLY file you are allowed to write to is the review file (you will be told its path when entering review mode).
4
4
 
5
- ## Review Process
5
+ ## Review Workflow
6
6
 
7
7
  ### Step 1: Gather Activity Context
8
8
  - Read the activity details to understand what was created/modified
9
9
  - Identify the artifacts by their sys_id and type
10
10
  - Note the Update Set associated with this activity
11
11
 
12
- ### Step 2: Analyze Created/Modified Code
12
+ ### Step 2: Discover Available Tools
13
+ Use the `tool_search` tool to discover available ServiceNow tools for analyzing artifacts, searching for existing code, and querying tables. This allows you to find the right tools dynamically rather than relying on hardcoded tool names.
14
+
15
+ ### Step 3: Analyze Created/Modified Code
13
16
  For each artifact in the activity:
14
- 1. Use `snow_analyze_artifact` to understand its structure and dependencies
17
+ 1. Use discovered analysis tools to understand its structure and dependencies
15
18
  2. Extract key functions and patterns from the code
16
19
  3. Identify GlideRecord queries and business logic
17
20
 
18
- ### Step 3: Search for Reuse Opportunities
19
- 1. Use `snow_find_artifact` to find existing Script Includes with similar functionality
20
- 2. Use `snow_comprehensive_search` to search for patterns matching the implemented functionality
21
- 3. Check for common naming conventions: *Utils, *Helper, *Service, *API
22
-
23
- ### Step 4: Code Pattern Analysis
24
- Look for these common reuse opportunities:
21
+ ### Step 4: Comprehensive Review
22
+ Evaluate the artifacts across these dimensions:
23
+
24
+ **Code Quality**
25
+ - Clean, readable code structure
26
+ - Proper error handling and logging
27
+ - ES5 compliance (ServiceNow uses Rhino engine)
28
+ - Consistent naming conventions
29
+
30
+ **Security**
31
+ - No hardcoded credentials or sensitive data
32
+ - Proper input validation and sanitization
33
+ - Appropriate ACL and role checks
34
+ - No injection vulnerabilities (GlideRecord query injection, XSS in widgets)
35
+
36
+ **Widget Coherence** (for Service Portal widgets)
37
+ - Server script initializes all data properties referenced in HTML
38
+ - Client script implements all methods called via ng-click
39
+ - Action names match between client c.server.get() calls and server input.action handlers
40
+ - No orphaned methods, data properties, or event handlers
41
+
42
+ **DRY & Reuse Opportunities**
43
+ - Search for existing Script Includes with similar functionality
44
+ - Look for common patterns: *Utils, *Helper, *Service, *API
45
+ - Check for duplicate GlideRecord queries and business logic
46
+ - Identify code that should be extracted to Script Includes for reuse
47
+
48
+ **Pattern Analysis**
25
49
  - GlideRecord utilities: Common query patterns, field value getters
26
50
  - Validation functions: Input validation, business rule conditions
27
51
  - Transformation logic: Data mapping, format conversion
@@ -29,71 +53,55 @@ Look for these common reuse opportunities:
29
53
  - Date/time utilities: Duration calculations, timezone handling
30
54
  - User/group utilities: Role checks, assignment logic
31
55
 
32
- ### Step 5: Generate Review Report
33
- Structure your findings as JSON:
34
-
35
- ```json
36
- {
37
- "activityId": "string",
38
- "reviewStatus": "approved" | "needs_revision",
39
- "summary": "Brief summary of findings",
40
- "artifactsReviewed": [
41
- {
42
- "sys_id": "string",
43
- "type": "widget|business_rule|client_script|etc",
44
- "name": "artifact name"
45
- }
46
- ],
47
- "reuseOpportunities": [
48
- {
49
- "type": "existing_script_include" | "duplicate_pattern" | "refactor_suggestion",
50
- "severity": "high" | "medium" | "low",
51
- "description": "What was found",
52
- "existingArtifact": {
53
- "sys_id": "optional - sys_id of existing Script Include",
54
- "name": "optional - name of existing artifact"
55
- },
56
- "recommendation": "Specific action to take",
57
- "codeLocation": "Where in the new code this applies"
58
- }
59
- ],
60
- "approved": true | false,
61
- "feedback": "If not approved, explanation for the developer"
62
- }
63
- ```
56
+ ### Step 5: Write Review Report
57
+ Write your findings to the review file. Structure as markdown with:
58
+
59
+ # Code Review
60
+
61
+ ## Summary
62
+ Brief summary of findings and decision (approved / needs revision).
63
+
64
+ ## Artifacts Reviewed
65
+ List of artifacts analyzed with type and name.
66
+
67
+ ## Findings
68
+ For each finding:
69
+ - **Category**: quality / security / coherence / dry / reuse
70
+ - **Severity**: high / medium / low
71
+ - **Description**: What was found
72
+ - **Existing Artifact**: Name and sys_id (if applicable, e.g., existing Script Include)
73
+ - **Recommendation**: Specific action to take
74
+ - **Code Location**: Where in the new code this applies
75
+
76
+ ## Decision
77
+ - **Approved**: yes / no
78
+ - **Feedback**: If not approved, detailed explanation for the developer
79
+
80
+ ### Step 6: Call review_exit
81
+ Once you have written your complete review to the review file, call `review_exit` to switch back to the build agent. The build agent will read your review file and act on the feedback.
64
82
 
65
83
  ## Decision Criteria
66
84
 
67
85
  ### Approve when:
86
+ - No critical security issues found
87
+ - Widget coherence is correct (if applicable)
68
88
  - No existing Script Includes provide equivalent functionality
69
89
  - Code patterns are unique to this use case
70
- - Minor optimizations possible but not blocking
71
- - Low-severity suggestions only (informational)
90
+ - Minor suggestions only (informational)
72
91
 
73
92
  ### Request Revision when:
93
+ - Security vulnerability detected
94
+ - Widget HTML/Client/Server scripts are misaligned
74
95
  - Existing Script Include provides >80% of needed functionality
75
96
  - Duplicate code detected that should be consolidated
76
97
  - High-severity code smell or anti-pattern detected
77
98
  - Business logic should be extracted to Script Include for reuse
78
99
 
79
- ## MCP Tools Available
80
-
81
- 1. **snow_analyze_artifact** - Analyze artifact structure and dependencies
82
- 2. **snow_find_artifact** - Find existing artifacts by name/type
83
- 3. **snow_comprehensive_search** - Deep search across all tables
84
- 4. **snow_query_table** - Query any ServiceNow table
85
-
86
100
  ## Important Guidelines
87
101
 
88
- 1. READ-ONLY: You cannot modify any code. Your role is purely analysis and feedback.
102
+ 1. READ-ONLY: You cannot modify any code. Only the review file can be written to.
89
103
  2. ES5 Awareness: ServiceNow uses ES5. If you see ES6+ syntax, flag it as a concern.
90
104
  3. Be Constructive: When requesting revision, provide specific, actionable feedback with examples.
91
105
  4. Consider Context: Not all code needs to be in Script Includes. Consider frequency of reuse, complexity, and scope.
92
106
  5. Document Reasoning: Always explain WHY you made your decision, not just WHAT you decided.
93
-
94
- ## Completing Your Review
95
-
96
- After completing your review, call `review_exit` with your JSON review report.
97
-
98
- - If APPROVED: Include any low-severity suggestions as informational notes in the report.
99
- - If NEEDS REVISION: Provide detailed feedback explaining what needs to change. The build agent will address the feedback.
107
+ 6. Your turn should only end with calling review_exit. Do not stop without calling it.
@@ -242,6 +242,13 @@ export namespace Session {
242
242
  return path.join(base, [input.time.created, input.slug].join("-") + ".md")
243
243
  }
244
244
 
245
+ export function review(input: { slug: string; time: { created: number } }) {
246
+ const base = Instance.project.vcs
247
+ ? path.join(Instance.worktree, ".snow-code", "reviews")
248
+ : path.join(Global.Path.data, "reviews")
249
+ return path.join(base, [input.time.created, input.slug].join("-") + ".md")
250
+ }
251
+
245
252
  export const get = fn(Identifier.schema("session"), async (id) => {
246
253
  const read = await Storage.read<Info>(["session", Instance.project.id, id])
247
254
  return read as Info
@@ -1,6 +1,7 @@
1
1
  <system-reminder>
2
2
  Your operational mode has changed from review to build.
3
3
  You are no longer in read-only analysis mode.
4
- The code review results have been provided. Act on the review feedback.
5
- If approved, proceed with activity_complete. If revision needed, address the feedback.
4
+ You are permitted to make file changes, run shell commands, and utilize your arsenal of tools as needed.
5
+ The code review results have been provided in the review file. Read it and act on the review feedback.
6
+ If approved, proceed with activity_complete. If revision needed, address the feedback first.
6
7
  </system-reminder>
@@ -1333,27 +1333,49 @@ NOTE: At any point in time through this workflow you should feel free to ask the
1333
1333
 
1334
1334
  // Switching from review to build
1335
1335
  if (input.agent.name === "build" && assistantMessage?.info.agent === "review") {
1336
- clonedUser.parts.push({
1337
- id: Identifier.ascending("part"),
1338
- messageID: userMessage.info.id,
1339
- sessionID: userMessage.info.sessionID,
1340
- type: "text",
1341
- text: REVIEW_SWITCH,
1342
- synthetic: true,
1343
- })
1336
+ const reviewPath = Session.review(input.session)
1337
+ const reviewExists = await Bun.file(reviewPath).exists()
1338
+ if (reviewExists) {
1339
+ const part = await Session.updatePart({
1340
+ id: Identifier.ascending("part"),
1341
+ messageID: userMessage.info.id,
1342
+ sessionID: userMessage.info.sessionID,
1343
+ type: "text",
1344
+ text:
1345
+ REVIEW_SWITCH +
1346
+ "\n\n" +
1347
+ `A review file exists at ${reviewPath}. You should read it and act on the review feedback within it`,
1348
+ synthetic: true,
1349
+ })
1350
+ clonedUser.parts.push(part)
1351
+ }
1344
1352
  return replaceUser()
1345
1353
  }
1346
1354
 
1347
1355
  // Entering review mode
1348
1356
  if (input.agent.name === "review" && assistantMessage?.info.agent !== "review") {
1349
- clonedUser.parts.push({
1357
+ const reviewPath = Session.review(input.session)
1358
+ const reviewExists = await Bun.file(reviewPath).exists()
1359
+ if (!reviewExists) await fs.mkdir(path.dirname(reviewPath), { recursive: true })
1360
+ const part = await Session.updatePart({
1350
1361
  id: Identifier.ascending("part"),
1351
1362
  messageID: userMessage.info.id,
1352
1363
  sessionID: userMessage.info.sessionID,
1353
1364
  type: "text",
1354
- text: `<system-reminder>\nReview mode is active. You are in READ-ONLY analysis mode.\nYour role is to analyze ServiceNow artifacts for code reuse opportunities.\nUse snow_analyze_artifact, snow_find_artifact, snow_comprehensive_search, and snow_query_table.\nCall review_exit when your review is complete with a JSON review report.\n</system-reminder>`,
1365
+ text: `<system-reminder>
1366
+ Review mode is active. You are in READ-ONLY analysis mode (except for the review file).
1367
+ Your role is to analyze ServiceNow artifacts for quality, security, coherence, and reuse opportunities.
1368
+ Use the tool_search tool to discover available ServiceNow tools for analysis.
1369
+
1370
+ ## Review File Info:
1371
+ ${reviewExists ? `A review file already exists at ${reviewPath}. You can read it and make incremental edits using the edit tool.` : `No review file exists yet. You should create your review at ${reviewPath} using the write tool.`}
1372
+ Write your review findings to this file. NOTE that this is the only file you are allowed to edit.
1373
+
1374
+ When your review is complete, call review_exit to switch back to the build agent.
1375
+ </system-reminder>`,
1355
1376
  synthetic: true,
1356
1377
  })
1378
+ clonedUser.parts.push(part)
1357
1379
  return replaceUser()
1358
1380
  }
1359
1381
 
@@ -1,8 +1,8 @@
1
- Use this tool to switch to the review agent for automated code reuse review of ServiceNow artifacts.
1
+ Use this tool to switch to the review agent for automated review of ServiceNow artifacts.
2
2
 
3
3
  Call this tool when:
4
4
  - An activity has been set to 'review' status (activity_update response contains reviewAvailable: true)
5
- - The user explicitly requests a code reuse review
5
+ - The user explicitly requests a code review
6
6
  - Artifacts are ready to be analyzed before completion
7
7
 
8
8
  This tool will ask the user if they want to switch to the review agent.
@@ -1,10 +1,10 @@
1
- Use this tool when you have completed the code reuse review and are ready to exit review mode.
1
+ Use this tool when you have completed the review and are ready to exit review mode.
2
2
 
3
3
  This tool will ask the user if they want to switch back to the build agent.
4
4
 
5
5
  Call this tool:
6
- - After you have completed the code reuse analysis
7
- - After you have generated a JSON review report with your findings
6
+ - After you have completed the code review and analysis
7
+ - After you have generated a review report with your findings
8
8
  - When you are confident the review is thorough and complete
9
9
 
10
10
  Do NOT call this tool:
@@ -1,10 +1,12 @@
1
1
  import z from "zod"
2
+ import path from "path"
2
3
  import { Tool } from "./tool"
3
4
  import { Question } from "../question"
4
5
  import { Session } from "../session"
5
6
  import { MessageV2 } from "../session/message-v2"
6
7
  import { Identifier } from "../id/id"
7
8
  import { Provider } from "../provider/provider"
9
+ import { Instance } from "../project/instance"
8
10
  import EXIT_DESCRIPTION from "./review-exit.txt"
9
11
  import ENTER_DESCRIPTION from "./review-enter.txt"
10
12
 
@@ -17,16 +19,15 @@ async function getLastModel(sessionID: string) {
17
19
 
18
20
  export const ReviewExitTool = Tool.define("review_exit", {
19
21
  description: EXIT_DESCRIPTION,
20
- parameters: z.object({
21
- reviewResult: z.string().optional().describe("JSON review report with findings"),
22
- approved: z.boolean().optional().describe("Whether the review approved the artifacts"),
23
- }),
24
- async execute(params, ctx) {
22
+ parameters: z.object({}),
23
+ async execute(_params, ctx) {
24
+ const session = await Session.get(ctx.sessionID)
25
+ const reviewFile = path.relative(Instance.worktree, Session.review(session))
25
26
  const answers = await Question.ask({
26
27
  sessionID: ctx.sessionID,
27
28
  questions: [
28
29
  {
29
- question: `Code reuse review is complete. Would you like to switch back to the build agent?`,
30
+ question: `Review at ${reviewFile} is complete. Would you like to switch to the build agent and start acting on the feedback?`,
30
31
  header: "Build Agent",
31
32
  custom: false,
32
33
  options: [
@@ -54,20 +55,12 @@ export const ReviewExitTool = Tool.define("review_exit", {
54
55
  model,
55
56
  }
56
57
  await Session.updateMessage(userMsg)
57
-
58
- const reviewSummary = params.reviewResult
59
- ? `\n\nReview result:\n${params.reviewResult}`
60
- : ""
61
- const approvalStatus = params.approved !== undefined
62
- ? `\nApproved: ${params.approved}`
63
- : ""
64
-
65
58
  await Session.updatePart({
66
59
  id: Identifier.ascending("part"),
67
60
  messageID: userMsg.id,
68
61
  sessionID: ctx.sessionID,
69
62
  type: "text",
70
- text: `The code reuse review has been completed.${approvalStatus}${reviewSummary}`,
63
+ text: `The review at ${reviewFile} has been approved, you can now edit files. Act on the review feedback`,
71
64
  synthetic: true,
72
65
  } satisfies MessageV2.TextPart)
73
66
 
@@ -87,15 +80,18 @@ export const ReviewEnterTool = Tool.define("review_enter", {
87
80
  updateSetName: z.string().optional().describe("Name of the update set being reviewed"),
88
81
  }),
89
82
  async execute(params, ctx) {
83
+ const session = await Session.get(ctx.sessionID)
84
+ const reviewFile = path.relative(Instance.worktree, Session.review(session))
85
+
90
86
  const answers = await Question.ask({
91
87
  sessionID: ctx.sessionID,
92
88
  questions: [
93
89
  {
94
- question: `Activity is ready for code reuse review. Would you like to switch to the review agent?`,
90
+ question: `Activity is ready for review. Would you like to switch to the review agent and save findings to ${reviewFile}?`,
95
91
  header: "Review Mode",
96
92
  custom: false,
97
93
  options: [
98
- { label: "Yes", description: "Switch to review agent for code reuse analysis" },
94
+ { label: "Yes", description: "Switch to review agent for code review and analysis" },
99
95
  { label: "No", description: "Stay with build agent and skip review" },
100
96
  ],
101
97
  },
@@ -121,7 +117,8 @@ export const ReviewEnterTool = Tool.define("review_enter", {
121
117
  await Session.updateMessage(userMsg)
122
118
 
123
119
  const context = [
124
- "User has requested to enter review mode. Switch to review mode and begin code reuse analysis.",
120
+ "User has requested to enter review mode. Switch to review mode and begin code review.",
121
+ `The review file will be at ${reviewFile}.`,
125
122
  params.activityId ? `Activity ID: ${params.activityId}` : "",
126
123
  params.updateSetName ? `Update Set: ${params.updateSetName}` : "",
127
124
  params.artifacts ? `Artifacts to review:\n${params.artifacts}` : "",
@@ -140,7 +137,7 @@ export const ReviewEnterTool = Tool.define("review_enter", {
140
137
 
141
138
  return {
142
139
  title: "Switching to review agent",
143
- output: "User confirmed to switch to review mode. A new message has been created to switch you to review mode. Begin code reuse analysis.",
140
+ output: `User confirmed to switch to review mode. A new message has been created to switch you to review mode. The review file will be at ${reviewFile}. Begin code review.`,
144
141
  metadata: {},
145
142
  }
146
143
  },