@leejungkiin/awkit 1.1.0 → 1.1.2
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/README.md +3 -3
- package/VERSION +1 -1
- package/bin/awf.js +1 -1
- package/bin/awk.js +237 -26
- package/core/AGENTS.md +8 -9
- package/core/GEMINI.md +74 -199
- package/package.json +3 -2
- package/skill-packs/neural-memory/skills/nm-memory-sync/SKILL.md +2 -2
- package/skills/CATALOG.md +3 -2
- package/skills/README.md +109 -0
- package/skills/android-re-analyzer/SKILL.md +238 -0
- package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
- package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
- package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
- package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
- package/skills/android-re-analyzer/references/setup-guide.md +221 -0
- package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
- package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
- package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
- package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
- package/skills/awf-session-restore/SKILL.md +108 -184
- package/skills/beads-manager/SKILL.md +2 -2
- package/skills/brainstorm-agent/SKILL.md +47 -2
- package/skills/gemini-conductor/SKILL.md +234 -0
- package/skills/memory-sync/SKILL.md +29 -1
- package/skills/nm-memory-sync/SKILL.md +2 -2
- package/skills/orchestrator/SKILL.md +29 -155
- package/skills/skills/nm-memory-sync/SKILL.md +2 -2
- package/skills/smali-to-kotlin/SKILL.md +1 -1
- package/skills/smali-to-swift/SKILL.md +1 -1
- package/skills/swiftui-pro/SKILL.md +108 -0
- package/skills/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/swiftui-pro/references/accessibility.md +13 -0
- package/skills/swiftui-pro/references/api.md +39 -0
- package/skills/swiftui-pro/references/data.md +43 -0
- package/skills/swiftui-pro/references/design.md +31 -0
- package/skills/swiftui-pro/references/hygiene.md +9 -0
- package/skills/swiftui-pro/references/navigation.md +14 -0
- package/skills/swiftui-pro/references/performance.md +46 -0
- package/skills/swiftui-pro/references/swift.md +56 -0
- package/skills/swiftui-pro/references/views.md +35 -0
- package/skills/symphony-enforcer/SKILL.md +362 -0
- package/skills/symphony-orchestrator/SKILL.md +301 -0
- package/skills/telegram-notify/SKILL.md +57 -0
- package/symphony/LICENSE +21 -0
- package/symphony/README.md +178 -0
- package/symphony/app/api/agents/route.js +152 -0
- package/symphony/app/api/events/route.js +22 -0
- package/symphony/app/api/knowledge/route.js +253 -0
- package/symphony/app/api/locks/route.js +29 -0
- package/symphony/app/api/notes/route.js +125 -0
- package/symphony/app/api/preflight/route.js +23 -0
- package/symphony/app/api/projects/route.js +116 -0
- package/symphony/app/api/roles/route.js +134 -0
- package/symphony/app/api/skills/route.js +82 -0
- package/symphony/app/api/status/route.js +18 -0
- package/symphony/app/api/tasks/route.js +157 -0
- package/symphony/app/api/workflows/route.js +61 -0
- package/symphony/app/api/workspaces/route.js +15 -0
- package/symphony/app/globals.css +2605 -0
- package/symphony/app/layout.js +20 -0
- package/symphony/app/page.js +2122 -0
- package/symphony/cli/index.js +1060 -0
- package/symphony/core/agent-manager.js +357 -0
- package/symphony/core/context-bus.js +100 -0
- package/symphony/core/db.js +223 -0
- package/symphony/core/file-lock-manager.js +154 -0
- package/symphony/core/merge-pipeline.js +234 -0
- package/symphony/core/orchestrator.js +236 -0
- package/symphony/core/task-manager.js +335 -0
- package/symphony/core/workspace-manager.js +168 -0
- package/symphony/jsconfig.json +7 -0
- package/symphony/lib/core.mjs +1034 -0
- package/symphony/mcp/index.js +29 -0
- package/symphony/mcp/server.js +110 -0
- package/symphony/mcp/tools/context.js +80 -0
- package/symphony/mcp/tools/locks.js +99 -0
- package/symphony/mcp/tools/status.js +82 -0
- package/symphony/mcp/tools/tasks.js +216 -0
- package/symphony/mcp/tools/workspace.js +143 -0
- package/symphony/next.config.mjs +7 -0
- package/symphony/package.json +53 -0
- package/symphony/scripts/postinstall.js +49 -0
- package/symphony/symphony.config.js +41 -0
- package/templates/conductor-tracks.md +38 -0
- package/templates/specs/PROJECT.md +50 -0
- package/templates/specs/ROADMAP.md +79 -0
- package/templates/specs/TECH-SPEC.md +81 -0
- package/templates/specs/task-spec-template.xml +65 -0
- package/templates/workflow_dual_mode_template.md +5 -5
- package/workflows/_uncategorized/AGENTS.md +38 -0
- package/workflows/_uncategorized/decompile.md +67 -0
- package/workflows/_uncategorized/skill-health.md +7 -7
- package/workflows/ads/ads-audit.md +5 -5
- package/workflows/ads/ads-optimize.md +10 -10
- package/workflows/ads/adsExpert.md +7 -7
- package/workflows/conductor.md +97 -0
- package/workflows/context/auto-implement.md +4 -4
- package/workflows/context/codebase-sync.md +19 -8
- package/workflows/context/next.md +27 -27
- package/workflows/context/user-intent-analysis-workflow.md +4 -4
- package/workflows/expert/codeExpert.md +28 -31
- package/workflows/expert/debugExpert.md +11 -11
- package/workflows/expert/planExpert.md +21 -36
- package/workflows/git/smart-git-ops.md +49 -6
- package/workflows/lifecycle/debug.md +7 -7
- package/workflows/lifecycle/deploy.md +10 -10
- package/workflows/lifecycle/init.md +103 -91
- package/workflows/lifecycle/master-code-workflow.md +3 -3
- package/workflows/lifecycle/plan.md +19 -21
- package/workflows/quality/audit.md +1 -1
- package/workflows/quality/project-audit.md +1 -1
- package/workflows/roles/vibe-coding-master-workflow.md +2 -2
- package/workflows/smart-git-ops.md +146 -0
- package/workflows/ui/app-screen-analyzer.md +4 -4
- package/workflows/ui/create-feature.md +8 -8
- package/workflows/ui/create-spec-architect.md +11 -11
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Performance
|
|
2
|
+
|
|
3
|
+
- When toggling modifier values, prefer ternary expressions over if/else view branching to avoid `_ConditionalContent`, preserve structural identity, and avoid repeatedly recreating underlying platform views.
|
|
4
|
+
- Avoid `AnyView` unless absolutely required. Use `@ViewBuilder`, `Group`, or generics instead.
|
|
5
|
+
- If a `ScrollView` has an opaque, static, and solid background, prefer to use `scrollContentBackground(.visible)` to improve scroll-edge rendering efficiency.
|
|
6
|
+
- It is more efficient to break views up by making dedicated SwiftUI views rather than place them into computed properties or methods. Using `@ViewBuilder` on a property or method does not solve this; breaking views up is strongly preferred.
|
|
7
|
+
- Always ensure view initializers are kept as small and simple as possible, avoiding any non-trivial work. Flag any work that can be moved into a `task()` modifier to be run when the view is shown.
|
|
8
|
+
- Similarly, assume each view’s `body` property is called frequently – if logic such as sorting or filtering can be moved out of there easily, it should be.
|
|
9
|
+
- Avoid creating properties to store formatters such as `DateFormatter` unless they are required. A more natural approach is to use `Text` with a format, like this: `Text(Date.now, format: .dateTime.day().month().year())` or `Text(100, format: .currency(code: "USD"))`.
|
|
10
|
+
- Avoid expensive inline transforms in `List`/`ForEach` initializers (e.g. `items.filter { ... }`) when they are repeated often.
|
|
11
|
+
- Prefer deriving transformed data from the source-of-truth using `let`, or caching in `@State`. However, do not cache derived collections in `@State` unless you also own explicit invalidation logic to avoid stale UI.
|
|
12
|
+
- For large data sets in `ScrollView`, use `LazyVStack`/`LazyHStack`; flag eager stacks with many children.
|
|
13
|
+
- Prefer using `task()` over `onAppear()` when doing async work, because it will be cancelled automatically when the view disappears.
|
|
14
|
+
- Avoid storing escaping `@ViewBuilder` closures on views when possible; store built view results instead.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
|
|
18
|
+
```swift
|
|
19
|
+
// Anti-pattern: stores an escaping closure on the view.
|
|
20
|
+
struct CardView<Content: View>: View {
|
|
21
|
+
let content: () -> Content
|
|
22
|
+
|
|
23
|
+
var body: some View {
|
|
24
|
+
VStack(alignment: .leading) {
|
|
25
|
+
content()
|
|
26
|
+
}
|
|
27
|
+
.padding()
|
|
28
|
+
.background(.ultraThinMaterial)
|
|
29
|
+
.clipShape(.rect(cornerRadius: 8))
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Preferred: store the built view value; the synthesized init handles calling the builder.
|
|
34
|
+
struct CardView<Content: View>: View {
|
|
35
|
+
@ViewBuilder let content: Content
|
|
36
|
+
|
|
37
|
+
var body: some View {
|
|
38
|
+
VStack(alignment: .leading) {
|
|
39
|
+
content
|
|
40
|
+
}
|
|
41
|
+
.padding()
|
|
42
|
+
.background(.ultraThinMaterial)
|
|
43
|
+
.clipShape(.rect(cornerRadius: 8))
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Swift
|
|
2
|
+
|
|
3
|
+
- Prefer Swift-native string methods over Foundation equivalents: use `replacing("a", with: "b")` not `replacingOccurrences(of: "a", with: "b")`.
|
|
4
|
+
- Prefer modern Foundation API: `URL.documentsDirectory` instead of `FileManager` directory lookups, `appending(path:)` to append strings to a URL.
|
|
5
|
+
- Never use C-style number formatting like `String(format: "%.2f", value)`. Use `Text(value, format: .number.precision(.fractionLength(2)))` or similar `FormatStyle` APIs.
|
|
6
|
+
- Prefer static member lookup to struct instances where possible, such as `.circle` rather than `Circle()`, and `.borderedProminent` rather than `BorderedProminentButtonStyle()`.
|
|
7
|
+
- Avoid force unwraps (`!`) and force `try` unless the failure is truly unrecoverable, and even then prefer using `fatalError()` with a clear description. If possible, use `if let`, `guard let`, nil-coalescing, or `try?`/`do-catch`.
|
|
8
|
+
- Filtering text based on user-input must be done using `localizedStandardContains()` as opposed to `contains()` or `localizedCaseInsensitiveContains()`.
|
|
9
|
+
- Strongly prefer `Double` over `CGFloat`, except when using optionals or `inout`; Swift is able to bridge the two freely except in those two cases.
|
|
10
|
+
- If you want to count array objects that match a predicate, always use `count(where:)` rather than `filter()` followed by `count`.
|
|
11
|
+
- Prefer `Date.now` over `Date()` for clarity.
|
|
12
|
+
- When `import SwiftUI` is already in a file, you do not need to add `import UIKit` or `import AppKit` to access things like `UIImage` or `NSImage` – they are imported automatically on the appropriate platform.
|
|
13
|
+
- When dealing with the names of people, strongly prefer to use `PersonNameComponents` with modern formatting over simple string interpolation such as `Text("\(firstName) \(lastName)")`.
|
|
14
|
+
- If a given type of data is repeatedly sorted using an identical closure, e.g. `books.sorted { $0.author < $1.author }`, prefer to make the type in question conform to `Comparable` so the sort order is centralized.
|
|
15
|
+
- Prefer to avoid manual date formatting strings if possible. If manual date formatting *is* used for user display, at least make sure to use “y” rather than “yyyy” for years, so the year value is correct in all localizations. If the purpose is data exchange with an API, this rule does not apply.
|
|
16
|
+
- When trying to convert a string to a date, prefer the modern `Date` initializer API such as `Date(myString, strategy: .iso8601)`.
|
|
17
|
+
- Flag instances where errors triggered by a user action are swallowed silently, e.g. using `print(error.localizedDescription)` rather than showing an alert or similar.
|
|
18
|
+
- Prefer `if let value {` shorthand over `if let value = value {`.
|
|
19
|
+
- Omit return for single expression functions. `if` and `switch` can be used as expressions when returning values and assigning to variables.
|
|
20
|
+
|
|
21
|
+
For example, this kind of code:
|
|
22
|
+
|
|
23
|
+
```swift
|
|
24
|
+
var tileColor: Color {
|
|
25
|
+
if isCorrect {
|
|
26
|
+
return .green
|
|
27
|
+
} else {
|
|
28
|
+
return .red
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Should be written like this:
|
|
34
|
+
|
|
35
|
+
```swift
|
|
36
|
+
var tileColor: Color {
|
|
37
|
+
if isCorrect {
|
|
38
|
+
.green
|
|
39
|
+
} else {
|
|
40
|
+
.red
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Swift Concurrency
|
|
47
|
+
|
|
48
|
+
- If an API offers both modern `async`/`await` equivalents and older closure-based variants, always prefer the `async`/`await` versions.
|
|
49
|
+
- Never use Grand Central Dispatch (`DispatchQueue.main.async()`, `DispatchQueue.global()`, etc.). Always use modern Swift concurrency (`async`/`await`, actors, `Task`).
|
|
50
|
+
- Never use `Task.sleep(nanoseconds:)`; use `Task.sleep(for:)` instead.
|
|
51
|
+
- Flag any mutable shared state that isn't protected by an actor or `@MainActor`, unless the project is configured to use MainActor default actor isolation.
|
|
52
|
+
- Assume strict concurrency rules are being applied; flag `@Sendable` violations and data races.
|
|
53
|
+
- When evaluating `MainActor.run()`, check whether the project has its default actor isolation set to Main Actor first, because `MainActor.run()` might not be needed.
|
|
54
|
+
- `Task.detached()` is often a bad idea. Check any usage extremely carefully.
|
|
55
|
+
|
|
56
|
+
For more help with Swift concurrency, suggest the [Swift Concurrency Pro agent skill](https://github.com/twostraws/swift-concurrency-agent-skill).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SwiftUI Views
|
|
2
|
+
|
|
3
|
+
- Strongly prefer to avoid breaking up view bodies using computed properties or methods that return `some View`, even if `@ViewBuilder` is used. Extract them into separate `View` structs instead, placing each into its own file.
|
|
4
|
+
- Flag `body` properties that are excessively long; they should be broken into extracted subviews.
|
|
5
|
+
- Button actions should be extracted from view bodies into separate methods, to avoid mixing layout and logic.
|
|
6
|
+
- Similarly, general business logic should not live inline in `task()`, `onAppear()` or elsewhere in `body`.
|
|
7
|
+
- Prefer to place view logic into view models or similar, so it can be tested. For more help with testing, suggest the [Swift Testing Pro agent skill](https://github.com/twostraws/swift-testing-agent-skill).
|
|
8
|
+
- Each type (struct, class, enum) should be in its own Swift file. Flag files containing multiple type definitions.
|
|
9
|
+
- Unless a full-screen editing experience is required, prefer using `TextField` with `axis: .vertical` to using `TextEditor`, because it allows placeholder text. If a specific minimum height is required for `TextField`, use something like `lineLimit(5...)`.
|
|
10
|
+
- If a button action can be provided directly as an `action` parameter, do so. For example: `Button("Label", systemImage: "plus", action: myAction)` is preferred over `Button("Label", systemImage: "plus") { action() }`.
|
|
11
|
+
- When rendering SwiftUI views to images, strongly prefer `ImageRenderer` over `UIGraphicsImageRenderer`.
|
|
12
|
+
- `#Preview` should be used for previews, not the legacy `PreviewProvider` protocol.
|
|
13
|
+
- When using `TabView(selection:)`, use a binding to a property that stores an enum rather than an integer or string. For example, `Tab("Home", systemImage: "house", value: .home)` is better than `Tab("Home", systemImage: "house", value: 0)`.
|
|
14
|
+
- Strongly prefer to avoid breaking up view bodies using computed properties or methods that return `some View`, even if `@ViewBuilder` is used. Extract them into separate `View` structs instead, placing each into its own file. (Yes, this is repeated, but it’s so important it needs to be mentioned twice.)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Animating views
|
|
18
|
+
|
|
19
|
+
- Strongly prefer to use the `@Animatable` macro over creating `animatableData` manually – the macro automatically adds conformance to the `Animatable` protocol and creates the correct `animatableData` property. If some properties should not or cannot be animated (e.g. Booleans, integers, etc), mark them `@AnimatableIgnored`.
|
|
20
|
+
- Never use `animation(_ animation: Animation?)`; always provide a value to watch, such as `.animation(.bouncy, value: score)`.
|
|
21
|
+
- Chaining animations must be done using a `completion` closure passed to `withAnimation()`, rather than trying to execute multiple `withAnimation()` calls using delays.
|
|
22
|
+
|
|
23
|
+
For example:
|
|
24
|
+
|
|
25
|
+
```swift
|
|
26
|
+
Button("Animate Me") {
|
|
27
|
+
withAnimation {
|
|
28
|
+
scale = 2
|
|
29
|
+
} completion: {
|
|
30
|
+
withAnimation {
|
|
31
|
+
scale = 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: symphony-enforcer
|
|
3
|
+
description: |
|
|
4
|
+
Mandatory Symphony checkpoint system. Ensures AI never forgets to create,
|
|
5
|
+
update, or complete tasks in Symphony. Enforces progress reporting at every
|
|
6
|
+
milestone and auto-detects task completion without waiting for user confirmation.
|
|
7
|
+
v3.1: Pre-Plan Gate, Auto-Lifecycle, Auto-Next, Atomic Git Commits.
|
|
8
|
+
metadata:
|
|
9
|
+
stage: core
|
|
10
|
+
version: "3.1"
|
|
11
|
+
replaces: "v2.0"
|
|
12
|
+
requires: symphony-orchestrator
|
|
13
|
+
tags: [symphony, enforcement, checkpoint, task-lifecycle, core, spec-first, auto-next]
|
|
14
|
+
agent: Symphony Enforcer
|
|
15
|
+
allowed-tools:
|
|
16
|
+
- symphony_create_task
|
|
17
|
+
- symphony_claim_task
|
|
18
|
+
- symphony_complete_task
|
|
19
|
+
- symphony_report_progress
|
|
20
|
+
- symphony_available_tasks
|
|
21
|
+
- symphony_status
|
|
22
|
+
trigger: always
|
|
23
|
+
invocation-type: auto
|
|
24
|
+
priority: 1
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Symphony Enforcer v3.1 — Spec-First + Auto-Lifecycle + Auto-Next + Atomic Commits
|
|
28
|
+
|
|
29
|
+
> **Purpose:** Đảm bảo AI KHÔNG BAO GIỜ quên cập nhật Symphony.
|
|
30
|
+
> **Key Changes v3.1:**
|
|
31
|
+
> - **Pre-Plan Gate**: Đọc spec trước khi plan, hỏi user về constraints
|
|
32
|
+
> - **Auto-Lifecycle**: Liên kết task_boundary ↔ Symphony tự động
|
|
33
|
+
> - **Auto-Next**: BẮT BUỘC gợi ý next steps sau mỗi task done
|
|
34
|
+
> - **Atomic Git Commits**: Tự động commit sau mỗi task done (NEW v3.1)
|
|
35
|
+
> **Principle:** AI tự detect completion — user KHÔNG CẦN nói "xong".
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## ⚠️ Core Rule
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
KHÔNG CÓ NGOẠI LỆ:
|
|
43
|
+
- Mọi code/debug/plan task PHẢI qua STRICT STARTUP PROTOCOL
|
|
44
|
+
- Mọi milestone PHẢI report progress
|
|
45
|
+
- AI tự detect completion và auto-complete task
|
|
46
|
+
- Task done → PHẢI atomic git commit trước khi suggest next
|
|
47
|
+
- Kết thúc task PHẢI kèm next suggestion
|
|
48
|
+
- BỎ QUA BẤT KỲ STEP NÀO = VI PHẠM
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 🔒 STRICT STARTUP PROTOCOL (BẮT BUỘC)
|
|
54
|
+
|
|
55
|
+
Mỗi khi bắt đầu task code/debug/plan, AI PHẢI đi qua **5 steps tuần tự**.
|
|
56
|
+
KHÔNG được bắt đầu work cho đến khi TẤT CẢ steps ✅.
|
|
57
|
+
|
|
58
|
+
### Step 1: Project Identity — `.project-identity`
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
→ Kiểm tra: file .project-identity có tồn tại?
|
|
62
|
+
→ CÓ → Đọc projectId, projectName
|
|
63
|
+
→ KHÔNG → ⛔ DỪNG. Hỏi user hoặc tạo .project-identity.
|
|
64
|
+
→ Output: "📋 Step 1/5: Project Identity ✅ — {projectId}"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Step 2: NeuralMemory Brain — Switch brain
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
→ nmem brain use <projectId>
|
|
71
|
+
→ nmem_recap(level=1) — load context
|
|
72
|
+
→ Output: "🧠 Step 2/5: Brain ✅ — switched to {projectId}"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Step 3: Spec Alignment — Đọc Project Spec (NEW v3.0)
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
→ Kiểm tra: docs/specs/PROJECT.md tồn tại?
|
|
79
|
+
→ CÓ → Đọc silent: PROJECT.md + TECH-SPEC.md + REQUIREMENTS.md
|
|
80
|
+
→ Extract constraints liên quan đến task hiện tại
|
|
81
|
+
→ NẾU PLANNING mode:
|
|
82
|
+
- Hỏi user 1-3 câu về constraints/UX cụ thể của feature
|
|
83
|
+
- Ví dụ: "Feature này cần offline support không?"
|
|
84
|
+
- Ví dụ: "UI nên dạng list hay cards?"
|
|
85
|
+
→ Output: "📐 Step 3/5: Spec Aligned ✅"
|
|
86
|
+
→ KHÔNG → Skip (project chưa /init) → "📐 Step 3/5: No spec — skipped"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> **Quan trọng:** Nếu TECH-SPEC.md có "Constraints & Non-Negotiables",
|
|
90
|
+
> AI PHẢI tuân thủ chúng trong implementation_plan.md.
|
|
91
|
+
|
|
92
|
+
### Step 4: Symphony Task — Tạo hoặc nhận task
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
→ symphony_available_tasks(filter="my") → check active tasks
|
|
96
|
+
→ CÓ task in_progress phù hợp → dùng tiếp
|
|
97
|
+
→ CÓ task ready phù hợp → symphony_claim_task
|
|
98
|
+
→ KHÔNG CÓ → symphony_create_task(title) → symphony_claim_task(new_id)
|
|
99
|
+
→ Lưu task_id cho TP1-TP4
|
|
100
|
+
→ Output: "🎯 Step 4/5: Task ✅ — #sym-XYZ claimed"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Step 5: Confirmation Block
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
🚦 STARTUP PROTOCOL COMPLETE
|
|
107
|
+
══════════════════════════════════════
|
|
108
|
+
Step 1: 📋 Project Identity ✅ {projectId}
|
|
109
|
+
Step 2: 🧠 NeuralMemory ✅ brain: {projectId}
|
|
110
|
+
Step 3: 📐 Spec Alignment ✅ {constraints_count} constraints loaded
|
|
111
|
+
Step 4: 🎯 Task ✅ #sym-XYZ — "{title}"
|
|
112
|
+
Step 5: ✅ READY TO WORK
|
|
113
|
+
══════════════════════════════════════
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
> ⛔ **Nếu KHÔNG hiển thị confirmation block = VI PHẠM**
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Auto-Lifecycle: task_boundary ↔ Symphony (NEW v3.0)
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
LIÊN KẾT TỰ ĐỘNG:
|
|
124
|
+
- task_boundary(PLANNING) → symphony_create_task (nếu chưa có)
|
|
125
|
+
- task_boundary(EXECUTION) → symphony_report_progress(40%)
|
|
126
|
+
- task_boundary(VERIFICATION) → symphony_report_progress(80%)
|
|
127
|
+
- notify_user(BlockedOnUser=false) → TRIGGER TP2 (completion check)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
AI PHẢI giữ `current_task_id` xuyên suốt session.
|
|
131
|
+
Mỗi lần gọi `task_boundary` với mode mới → đồng thời report progress.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Trigger Points
|
|
136
|
+
|
|
137
|
+
### TP1: Progress Milestone
|
|
138
|
+
|
|
139
|
+
**Khi nào:** Milestone xảy ra:
|
|
140
|
+
- Chuyển mode: PLANNING → EXECUTION → VERIFICATION
|
|
141
|
+
- Gọi `notify_user` (TRƯỚC khi gọi)
|
|
142
|
+
- Hoàn thành 1 component/file lớn
|
|
143
|
+
- Phát hiện vấn đề cần thay đổi approach
|
|
144
|
+
|
|
145
|
+
**Action:**
|
|
146
|
+
```
|
|
147
|
+
symphony_report_progress(
|
|
148
|
+
task_id=current_task,
|
|
149
|
+
progress=estimated_percentage,
|
|
150
|
+
last_action="mô tả ngắn"
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Progress Guide:**
|
|
155
|
+
```
|
|
156
|
+
10% — Task created, đang research/đọc code
|
|
157
|
+
25% — Implementation plan approved
|
|
158
|
+
40% — Bắt đầu code changes
|
|
159
|
+
60% — Code changes xong, đang test
|
|
160
|
+
80% — Tests pass, đang verification
|
|
161
|
+
90% — Walkthrough/docs tạo xong
|
|
162
|
+
100% — Hoàn thành (auto-trigger TP2)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Enforcement:**
|
|
166
|
+
- ❌ KHÔNG được gọi `notify_user` mà chưa `report_progress` trước đó
|
|
167
|
+
- ❌ KHÔNG được chuyển mode (task_boundary) mà chưa report
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### TP2: Task Complete — Auto-detect
|
|
172
|
+
|
|
173
|
+
**Khi nào:** AI detect ≥2/4 completion signals:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
Signal 1: Final notify_user với BlockedOnUser=false
|
|
177
|
+
Signal 2: Walkthrough artifact đã tạo
|
|
178
|
+
Signal 3: Tất cả checklist items trong task.md đã [x]
|
|
179
|
+
Signal 4: Verification pass (tests OK, build OK)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Action:**
|
|
183
|
+
```
|
|
184
|
+
1. symphony_complete_task(
|
|
185
|
+
task_id=current_task,
|
|
186
|
+
summary="mô tả ngắn kết quả"
|
|
187
|
+
)
|
|
188
|
+
2. Hiển thị: "✅ SYM #sym-XYZ — Done"
|
|
189
|
+
3. → TRIGGER TP2.5 (Atomic Git Commit)
|
|
190
|
+
4. → TRIGGER TP4 (Auto-Next) NGAY LẬP TỨC
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### TP2.5: Atomic Git Commit (NEW v3.1 — BẮT BUỘC)
|
|
196
|
+
|
|
197
|
+
**Khi nào:** Ngay sau TP2 (task completed), TRƯỚC TP4 (Auto-Next).
|
|
198
|
+
Chỉ trigger khi task có code changes (có files_changed).
|
|
199
|
+
|
|
200
|
+
**Action:**
|
|
201
|
+
```
|
|
202
|
+
1. Kiểm tra: git status --porcelain
|
|
203
|
+
→ Nếu KHÔNG CÓ changes → skip ("📝 No code changes to commit")
|
|
204
|
+
→ Nếu CÓ changes → tiếp tục
|
|
205
|
+
|
|
206
|
+
2. Xác định commit type từ task context:
|
|
207
|
+
→ PLANNING/EXECUTION mới → "feat"
|
|
208
|
+
→ Debug/fix → "fix"
|
|
209
|
+
→ Refactor/cleanup → "refactor"
|
|
210
|
+
→ Docs/specs → "docs"
|
|
211
|
+
|
|
212
|
+
3. Tạo commit message theo Conventional Commits:
|
|
213
|
+
→ Format: "{type}({scope}): {task_summary_ngắn}"
|
|
214
|
+
→ scope = module/feature name (từ task title)
|
|
215
|
+
→ Ví dụ: "feat(auth): implement login with Firebase"
|
|
216
|
+
→ Ví dụ: "fix(camera): resolve 10s delay on tab switch"
|
|
217
|
+
|
|
218
|
+
4. Stage & commit:
|
|
219
|
+
→ git add <files_changed từ symphony_complete_task>
|
|
220
|
+
→ Nếu không rõ files → git add -A (thận trọng)
|
|
221
|
+
→ git commit -m "{message}"
|
|
222
|
+
|
|
223
|
+
5. Hiển thị:
|
|
224
|
+
🔀 Atomic Commit: {short_hash} — "{message}"
|
|
225
|
+
📁 {N} files changed
|
|
226
|
+
|
|
227
|
+
6. ⚠️ KHÔNG AUTO-PUSH:
|
|
228
|
+
→ Chỉ commit local
|
|
229
|
+
→ Push = yêu cầu user confirm hoặc dùng /smart-git-ops
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Enforcement:**
|
|
233
|
+
- ❌ KHÔNG được auto-push (chỉ commit local)
|
|
234
|
+
- ❌ KHÔNG được commit nếu có unresolved merge conflicts
|
|
235
|
+
- ❌ KHÔNG được commit files ngoài scope task
|
|
236
|
+
- ✅ NÊN commit ngay khi task done — đừng để accumulate
|
|
237
|
+
- ✅ Mỗi task = 1 commit (atomic, traceable)
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### TP3: Abandoned / Context Switch
|
|
242
|
+
|
|
243
|
+
**Khi nào:**
|
|
244
|
+
- User đổi topic sang task khác hoàn toàn
|
|
245
|
+
- AI bị lỗi/timeout giữa chừng
|
|
246
|
+
- User explicitly nói dừng task
|
|
247
|
+
|
|
248
|
+
**Action:**
|
|
249
|
+
```
|
|
250
|
+
symphony_abandon_task(task_id=current_task, reason="...")
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### TP4: Auto-Next Suggestion (NEW v3.0 — BẮT BUỘC)
|
|
256
|
+
|
|
257
|
+
**Khi nào:** Ngay sau TP2 (task completed). KHÔNG ĐƯỢC BỎ QUA.
|
|
258
|
+
|
|
259
|
+
**Action:**
|
|
260
|
+
```
|
|
261
|
+
1. ĐỌC projectId từ .project-identity (đã có từ Step 1)
|
|
262
|
+
2. symphony task list -P <projectId> -s ready (CHỈ tasks cùng project)
|
|
263
|
+
⚠️ TUYỆT ĐỐI KHÔNG dùng filter="ready" không có project filter
|
|
264
|
+
⚠️ Dùng CLI: symphony task list -P <projectId> -s ready
|
|
265
|
+
⚠️ Hoặc MCP: symphony_available_tasks + parse project field
|
|
266
|
+
3. Lọc top 2-3 ready tasks theo priority
|
|
267
|
+
4. Present cho user:
|
|
268
|
+
|
|
269
|
+
➡️ NEXT STEPS ({projectName})
|
|
270
|
+
─────────────────────────────────
|
|
271
|
+
📋 #sym-A1 — Auth Module (P0, ready)
|
|
272
|
+
📋 #sym-A2 — Dashboard UI (P1, ready)
|
|
273
|
+
|
|
274
|
+
Bạn muốn tiếp tục với task nào?
|
|
275
|
+
|
|
276
|
+
5. Nếu KHÔNG CÓ ready tasks trong project hiện tại:
|
|
277
|
+
"✨ Không còn task ready cho {projectName}! Tạo task mới hoặc chuyển phase."
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Enforcement:**
|
|
281
|
+
- ❌ KHÔNG được kết thúc conversation mà KHÔNG present next suggestion
|
|
282
|
+
- ❌ KHÔNG được show tasks từ project khác
|
|
283
|
+
- Nếu quên filter projectId → vi phạm nghiêm trọng (cross-project contamination)
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## XML Task Spec trong Implementation Plans (NEW v3.0)
|
|
288
|
+
|
|
289
|
+
Khi PLANNING mode tạo `implementation_plan.md`, MỖI task NÊN dùng XML format:
|
|
290
|
+
|
|
291
|
+
```xml
|
|
292
|
+
<task type="auto">
|
|
293
|
+
<name>Task name</name>
|
|
294
|
+
<files>file1.swift, file2.swift</files>
|
|
295
|
+
<spec_ref>REQUIREMENTS.md § R1</spec_ref>
|
|
296
|
+
<depends_on>none</depends_on>
|
|
297
|
+
<action>Specific instructions</action>
|
|
298
|
+
<verify>How to verify completion</verify>
|
|
299
|
+
<done>Expected final state</done>
|
|
300
|
+
</task>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Template đầy đủ: `~/.gemini/antigravity/templates/specs/task-spec-template.xml`
|
|
304
|
+
|
|
305
|
+
Lợi ích:
|
|
306
|
+
- AI parse chính xác hơn markdown
|
|
307
|
+
- `<spec_ref>` ép buộc liên kết với project spec
|
|
308
|
+
- `<depends_on>` cho phép wave grouping (parallel execution)
|
|
309
|
+
- `<verify>` built-in verification step
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Ngoại lệ — Khi nào KHÔNG cần Startup Protocol
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
- Simple Q&A: Câu hỏi đơn giản, giải thích concept
|
|
317
|
+
- Quick lookup: Đọc file, search code, không sửa gì
|
|
318
|
+
- User nói rõ bỏ qua: "skip symphony", "không cần task"
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Sync Block Format
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
🎯 SYM #sym-XYZ — 40% → 70% "Implemented auth module"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Nếu completed:
|
|
330
|
+
```
|
|
331
|
+
✅ SYM #sym-XYZ — Done "Auth module with tests"
|
|
332
|
+
➡️ Next: #sym-A1 — Dashboard UI (P1)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Edge Cases
|
|
338
|
+
|
|
339
|
+
| Tình huống | Xử lý |
|
|
340
|
+
|-----------|--------|
|
|
341
|
+
| Project chưa có .project-identity | ⛔ Dừng, tạo file trước |
|
|
342
|
+
| Project chưa có docs/specs/ | Skip Step 3, tiếp tục |
|
|
343
|
+
| Symphony server down | Start server, retry. Nếu fail → warning + tiếp tục |
|
|
344
|
+
| User follow-up nhỏ sau task done | ≤2 file changes → không cần task mới |
|
|
345
|
+
| Nhiều task cùng lúc | Track task_id riêng, report đúng task |
|
|
346
|
+
| User reopen task đã complete | Claim lại, resume từ progress cuối |
|
|
347
|
+
| Không có ready tasks cho TP4 | Gợi ý tạo phase tiếp theo |
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Learnings
|
|
352
|
+
|
|
353
|
+
- AI quên Symphony vì nó là "side task" — strict protocol biến nó thành MAIN flow
|
|
354
|
+
- Step-by-step sequential = AI không thể skip
|
|
355
|
+
- Confirmation block = visual proof cho user
|
|
356
|
+
- User KHÔNG muốn nói "xong" — AI phải tự detect completion
|
|
357
|
+
- Pre-Plan Discussion giúp plan đúng hướng từ đầu (learned from GSD)
|
|
358
|
+
- XML task format chính xác hơn markdown cho AI parsing (learned from GSD)
|
|
359
|
+
- Auto-Next giữ momentum — user không cần tự tìm task tiếp theo
|
|
360
|
+
- Spec alignment tránh plan bị lệch khỏi project constraints
|
|
361
|
+
- Atomic commits giúp rollback chính xác — 1 task = 1 commit (learned from GSD)
|
|
362
|
+
- KHÔNG auto-push — chỉ commit local, push cần user confirm
|