mirror of
https://github.com/msitarzewski/agency-agents.git
synced 2026-10-23 03:34:53 +00:00
Merge pull request #1175 from msitarzewski/integ/content-batch5-6
Merge @rudycelekli's content fixes, batch 5 (29 PRs, #1097–#1174), plus #1142
This commit is contained in:
28 files changed
+156
-94
No files matched your search
@@ -60,9 +60,12 @@ You are **UI Designer**, an expert user interface designer who creates beautiful
|
||||
/* Color Tokens */
|
||||
--color-primary-100: #f0f9ff;
|
||||
--color-primary-500: #3b82f6;
|
||||
--color-primary-600: #2563eb;
|
||||
--color-primary-900: #1e3a8a;
|
||||
|
||||
--color-secondary-100: #f3f4f6;
|
||||
--color-secondary-200: #e5e7eb;
|
||||
--color-secondary-300: #d1d5db;
|
||||
--color-secondary-500: #6b7280;
|
||||
--color-secondary-900: #111827;
|
||||
|
||||
@@ -196,13 +199,13 @@ You are **UI Designer**, an expert user interface designer who creates beautiful
|
||||
/* Small devices (640px and up) */
|
||||
@media (min-width: 640px) {
|
||||
.container { max-width: 640px; }
|
||||
.sm\\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
|
||||
.sm\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
|
||||
/* Medium devices (768px and up) */
|
||||
@media (min-width: 768px) {
|
||||
.container { max-width: 768px; }
|
||||
.md\\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
|
||||
.md\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
|
||||
}
|
||||
|
||||
/* Large devices (1024px and up) */
|
||||
@@ -212,7 +215,7 @@ You are **UI Designer**, an expert user interface designer who creates beautiful
|
||||
padding-left: var(--space-6);
|
||||
padding-right: var(--space-6);
|
||||
}
|
||||
.lg\\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
|
||||
.lg\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
|
||||
}
|
||||
|
||||
/* Extra large devices (1280px and up) */
|
||||
|
||||
@@ -59,11 +59,11 @@ You are a **Data Engineer**, an expert in designing, building, and operating the
|
||||
|
||||
## 📋 Your Technical Deliverables
|
||||
|
||||
### Spark Pipeline (PySpark + Delta Lake)
|
||||
### Spark Pipeline (open-source PySpark + Delta Lake)
|
||||
```python
|
||||
from datetime import date
|
||||
from pyspark.sql import SparkSession
|
||||
from pyspark.sql.functions import col, current_timestamp, sha2, concat_ws, lit
|
||||
from pyspark.sql.functions import col, current_timestamp, sha2, concat_ws, lit, input_file_name
|
||||
from delta.tables import DeltaTable
|
||||
|
||||
spark = SparkSession.builder \
|
||||
@@ -76,7 +76,7 @@ def ingest_bronze(source_path: str, bronze_table: str, source_system: str) -> in
|
||||
df = spark.read.format("json").option("inferSchema", "true").load(source_path)
|
||||
df = df.withColumn("_ingested_at", current_timestamp()) \
|
||||
.withColumn("_source_system", lit(source_system)) \
|
||||
.withColumn("_source_file", col("_metadata.file_path"))
|
||||
.withColumn("_source_file", input_file_name())
|
||||
df.write.format("delta").mode("append").option("mergeSchema", "true").save(bronze_table)
|
||||
return df.count()
|
||||
|
||||
@@ -123,6 +123,8 @@ def build_gold_daily_revenue(
|
||||
.save(gold_table)
|
||||
```
|
||||
|
||||
`_source_file` must describe the file Spark read, rather than a payload field named `_metadata.file_path`. This open-source Spark example uses [PySpark `input_file_name`](https://spark.apache.org/docs/3.5.6/api/python/reference/pyspark.sql/api/pyspark.sql.functions.input_file_name.html) so source JSON containing `_metadata` cannot replace the physical file URI. Adapt provenance to the runtime you deploy; the [Databricks file metadata API](https://docs.databricks.com/aws/en/ingestion/file-metadata-column) also documents collisions with source columns named `_metadata`.
|
||||
|
||||
Run the Gold refresh against a complete Silver snapshot for the requested date window, not a partial event batch. Delta `replaceWhere` replaces exactly that window even when the aggregate is empty; dates outside it must remain untouched. Keep its default predicate constraint check enabled. For example, refreshing `[2026-09-01, 2026-09-02)` after an order is refunded must remove the old September 1 revenue, while preserving September 2 and later results. See [Delta selective overwrite](https://docs.delta.io/delta-batch/#selective-overwrite).
|
||||
|
||||
### dbt Data Quality Contract
|
||||
|
||||
@@ -90,9 +90,10 @@ jobs:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build and Push
|
||||
run: |
|
||||
docker build -t app:${{ github.sha }} .
|
||||
docker build -t registry/app:${{ github.sha }} .
|
||||
docker push registry/app:${{ github.sha }}
|
||||
|
||||
deploy:
|
||||
|
||||
@@ -473,7 +473,7 @@ async function createApprovalInstance(params: {
|
||||
// Query approval instance details
|
||||
async function getApprovalInstance(instanceCode: string) {
|
||||
const resp = await client.approval.instance.get({
|
||||
params: { instance_id: instanceCode },
|
||||
path: { instance_id: instanceCode },
|
||||
});
|
||||
|
||||
if (resp.code !== 0) {
|
||||
|
||||
@@ -96,24 +96,30 @@ export const DataTable = memo<DataTableProps>(({ data, columns, onRowClick }) =>
|
||||
role="table"
|
||||
aria-label="Data table"
|
||||
>
|
||||
{rowVirtualizer.getVirtualItems().map((virtualItem) => {
|
||||
const row = data[virtualItem.index];
|
||||
return (
|
||||
<div
|
||||
key={virtualItem.key}
|
||||
className="flex items-center border-b hover:bg-gray-50 cursor-pointer"
|
||||
onClick={() => handleRowClick(row)}
|
||||
role="row"
|
||||
tabIndex={0}
|
||||
>
|
||||
{columns.map((column) => (
|
||||
<div key={column.key} className="px-4 py-2 flex-1" role="cell">
|
||||
{row[column.key]}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div role="rowgroup" style={{ height: rowVirtualizer.getTotalSize(), position: 'relative' }}>
|
||||
{rowVirtualizer.getVirtualItems().map((virtualItem) => {
|
||||
const row = data[virtualItem.index];
|
||||
return (
|
||||
<div
|
||||
key={virtualItem.key}
|
||||
className="flex items-center border-b hover:bg-gray-50 cursor-pointer"
|
||||
style={{
|
||||
position: 'absolute', top: 0, left: 0, width: '100%',
|
||||
height: virtualItem.size, transform: `translateY(${virtualItem.start}px)`,
|
||||
}}
|
||||
onClick={() => handleRowClick(row)}
|
||||
role="row"
|
||||
tabIndex={0}
|
||||
>
|
||||
{columns.map((column) => (
|
||||
<div key={column.key} className="px-4 py-2 flex-1" role="cell">
|
||||
{row[column.key]}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -255,7 +255,7 @@ slos:
|
||||
- severity: page
|
||||
short_window: 5m
|
||||
long_window: 1h
|
||||
burn_rate: 14.4x # budget exhausted in 2 hours
|
||||
burn_rate: 14.4x # budget exhausted in ~2 days (2% of it per hour)
|
||||
- severity: ticket
|
||||
short_window: 30m
|
||||
long_window: 6h
|
||||
|
||||
@@ -66,7 +66,8 @@ platform :android do
|
||||
aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH],
|
||||
release_status: "draft" # human promotes to phased production
|
||||
)
|
||||
upload_symbols_to_crashlytics # mapping.txt for deobfuscation
|
||||
# mapping.txt is uploaded by the Crashlytics Gradle plugin during the release
|
||||
# build; upload_symbols_to_crashlytics only handles iOS dSYMs
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
@@ -128,6 +128,12 @@ set firewall family inet filter PROTECT-RE term allow-ssh from source-address 10
|
||||
set firewall family inet filter PROTECT-RE term allow-ssh from protocol tcp
|
||||
set firewall family inet filter PROTECT-RE term allow-ssh from destination-port ssh
|
||||
set firewall family inet filter PROTECT-RE term allow-ssh then accept
|
||||
set firewall family inet filter PROTECT-RE term allow-bgp from source-address 203.0.113.1/32
|
||||
set firewall family inet filter PROTECT-RE term allow-bgp from protocol tcp
|
||||
set firewall family inet filter PROTECT-RE term allow-bgp from port bgp
|
||||
set firewall family inet filter PROTECT-RE term allow-bgp then accept
|
||||
set firewall family inet filter PROTECT-RE term allow-ospf from protocol ospf
|
||||
set firewall family inet filter PROTECT-RE term allow-ospf then accept
|
||||
set firewall family inet filter PROTECT-RE term drop-rest then discard
|
||||
set interfaces lo0 unit 0 family inet filter input PROTECT-RE
|
||||
```
|
||||
|
||||
@@ -89,6 +89,8 @@ func _ready() -> void:
|
||||
_current_health = max_health
|
||||
|
||||
func apply_damage(amount: float) -> void:
|
||||
if _current_health == 0.0:
|
||||
return # already dead; `died` must not fire again
|
||||
_current_health = clampf(_current_health - amount, 0.0, max_health)
|
||||
health_changed.emit(_current_health)
|
||||
if _current_health == 0.0:
|
||||
@@ -137,6 +139,8 @@ public partial class HealthComponent : Node
|
||||
|
||||
public void ApplyDamage(float amount)
|
||||
{
|
||||
if (_currentHealth == 0f)
|
||||
return; // already dead; Died must not fire again
|
||||
_currentHealth = Mathf.Clamp(_currentHealth - amount, 0f, MaxHealth);
|
||||
EmitSignal(SignalName.HealthChanged, _currentHealth);
|
||||
if (_currentHealth == 0f)
|
||||
|
||||
@@ -133,9 +133,13 @@ func send_input(direction: Vector2) -> void:
|
||||
velocity = direction.normalized() * 200.0
|
||||
move_and_slide()
|
||||
|
||||
# Server confirms a hit to all clients
|
||||
@rpc("authority", "reliable", "call_local")
|
||||
# Server confirms a hit to all clients. The node's authority is its owning
|
||||
# client, so accept the call from any peer and keep only the server's.
|
||||
@rpc("any_peer", "reliable", "call_local")
|
||||
func take_damage(amount: float) -> void:
|
||||
var sender_id := multiplayer.get_remote_sender_id()
|
||||
if sender_id != 0 and sender_id != MultiplayerPeer.TARGET_PEER_SERVER:
|
||||
return # Reject: only the server (peer 1) applies damage
|
||||
_health -= amount
|
||||
if _health <= 0.0:
|
||||
_on_died()
|
||||
|
||||
@@ -75,8 +75,8 @@ void fragment() {
|
||||
alpha = max(alpha, texture(TEXTURE, UV + vec2(-texel.x, -texel.y)).a);
|
||||
|
||||
// Draw outline where neighbor has alpha but current pixel does not
|
||||
vec4 outline = outline_color * vec4(1.0, 1.0, 1.0, alpha * (1.0 - base_color.a));
|
||||
COLOR = base_color + outline;
|
||||
vec4 outline = vec4(outline_color.rgb, outline_color.a * alpha * (1.0 - base_color.a));
|
||||
COLOR = mix(outline, base_color, base_color.a);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -128,7 +128,8 @@ void fragment() {
|
||||
|
||||
vec3 normal_a = texture(normal_map_a, UV * wave_scale + time_offset_a).rgb;
|
||||
vec3 normal_b = texture(normal_map_b, UV * wave_scale + time_offset_b).rgb;
|
||||
NORMAL_MAP = normalize(normal_a + normal_b);
|
||||
// Blend the encoded [0,1] texels; Godot decodes xy * 2 - 1 and rebuilds z
|
||||
NORMAL_MAP = mix(normal_a, normal_b, 0.5);
|
||||
|
||||
// Depth-based color blend (Forward+ / Mobile renderer required for DEPTH_TEXTURE)
|
||||
// In Compatibility renderer: remove depth blend, use flat shallow_color
|
||||
|
||||
@@ -218,21 +218,22 @@ Steps:
|
||||
-- Use AnalyticsService (Roblox's built-in, no third-party required)
|
||||
local AnalyticsService = game:GetService("AnalyticsService")
|
||||
|
||||
local function trackEvent(player: Player, eventName: string, params: {[string]: any}?)
|
||||
-- Roblox's built-in analytics — visible in Creator Dashboard
|
||||
AnalyticsService:LogCustomEvent(player, eventName, params or {})
|
||||
local function trackEvent(player: Player, eventName: string, value: number?)
|
||||
-- Roblox's built-in analytics — visible in Creator Dashboard.
|
||||
-- The third argument is a numeric value used in aggregation (default 1).
|
||||
AnalyticsService:LogCustomEvent(player, eventName, value or 1)
|
||||
end
|
||||
|
||||
-- Track onboarding completion
|
||||
trackEvent(player, "OnboardingCompleted", {time_seconds = elapsedTime})
|
||||
trackEvent(player, "OnboardingCompleted", elapsedTime) -- seconds
|
||||
|
||||
-- Track first purchase
|
||||
trackEvent(player, "FirstPurchase", {pass_name = passName, price_robux = price})
|
||||
trackEvent(player, "FirstPurchase", price) -- Robux
|
||||
|
||||
-- Track session length on leave
|
||||
Players.PlayerRemoving:Connect(function(player)
|
||||
local sessionLength = os.time() - sessionStartTimes[player.UserId]
|
||||
trackEvent(player, "SessionEnd", {duration_seconds = sessionLength})
|
||||
trackEvent(player, "SessionEnd", sessionLength) -- seconds
|
||||
end)
|
||||
```
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ local DataManager = {}
|
||||
|
||||
local playerDataStore = DataStoreService:GetDataStore("PlayerData_v1")
|
||||
local loadedData: {[number]: any} = {}
|
||||
local loadFailed: {[number]: boolean} = {}
|
||||
|
||||
local DEFAULT_DATA = {
|
||||
coins = 0,
|
||||
@@ -139,6 +140,7 @@ function DataManager.loadPlayerData(player: Player): ()
|
||||
else
|
||||
warn("[DataManager] Failed to load data for", player.Name, "- using defaults")
|
||||
loadedData[player.UserId] = deepCopy(DEFAULT_DATA)
|
||||
loadFailed[player.UserId] = true -- never save defaults over data we couldn't read
|
||||
end
|
||||
end
|
||||
|
||||
@@ -146,6 +148,11 @@ function DataManager.savePlayerData(player: Player): ()
|
||||
local key = "player_" .. player.UserId
|
||||
local data = loadedData[player.UserId]
|
||||
if not data then return end
|
||||
if loadFailed[player.UserId] then
|
||||
loadFailed[player.UserId] = nil
|
||||
loadedData[player.UserId] = nil
|
||||
return
|
||||
end
|
||||
|
||||
local success, err = retryAsync(function()
|
||||
playerDataStore:SetAsync(key, data)
|
||||
|
||||
@@ -115,6 +115,8 @@ public class PlayerController : NetworkBehaviour
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// Seed the authoritative position from the spawn point, not Vector3.zero
|
||||
if (IsServer) _serverPosition.Value = transform.position;
|
||||
if (!IsOwner) return;
|
||||
_clientPredictedPosition = transform.position;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ of adding hundreds of generated skills to `skills.external_dirs`. Hermes sees a
|
||||
small fixed tool surface at startup, while the complete Agency roster is
|
||||
stored on disk in `data/agents.json` and searched/loaded lazily.
|
||||
|
||||
Generated agent count: 279
|
||||
Generated agent count: 282
|
||||
|
||||
## Tools exposed to Hermes
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ agent ai-citation-strategist f22e416cb60b6fb1e8c1844d798346e7f30cf1cafbac931950f
|
||||
agent ai-data-remediation-engineer da4718e09a1348e2d3a992a5d36f0950cb37beff59ce9ea750c4f9df29805c65
|
||||
agent ai-engineer d93416c98c7462beb379753a9416ed94e8c4b8f5f680a3f1b7fb5904e60f703b
|
||||
agent ai-generated-code-security-auditor 0e706372c85d1c491e33bd505dccdb5cdbb86ec244e3a5d0c3a4c89afe77976b
|
||||
agent analytics-reporter ede9499def7458623cb2ea841d611801d6ec048df8e559725899d6d576a965b5
|
||||
agent analytics-reporter bb77a5067f08ad0d709f144124adf673edc7826e8671505e20d42e57f5415f88
|
||||
agent anthropologist c79922e2739ea11715729b4535e2b32f6c0d861cd1f12915bdfb4584eff05981
|
||||
agent api-platform-engineer 952d2e1552d5629fad4c5edef70d3531a4686daf3728450afeb9ac935eaaa3aa
|
||||
agent api-tester fc5016240261651d68832db41c41fb218b6b91f2db6ad1d5a45ace361a1b0bef
|
||||
agent app-store-optimizer 4b4f5e0cec69b402b824970817b23774b00f46e7ce0b3d2e3ebd3278cdfea002
|
||||
agent application-security-engineer 42f7ceeadf155ec77a2ecd037c9279783d1581773792494899ba8dc90ff3d631
|
||||
agent application-security-engineer 04ad0656d7263af4924cf95ef979857cb68b5bd4b41ab0397d6d3d7f3b0a7c3f
|
||||
agent ats-validator-architect bb4f34292a40e2a08c6ad8c8a222940c8c57a18b2d7001eb87f816aaf7e2c170
|
||||
agent automation-governance-architect 181383ad60f2f885b034b1dd3560e77c906eaf102540e601c5bd23008fe6d83c
|
||||
agent autonomous-optimization-architect 0d2e8afca25182fdd131577bb7e240750738cfecefff9402a0fbc2b9e0dc9408
|
||||
@@ -57,7 +57,7 @@ agent cultural-intelligence-strategist a2fcfd37a164bc8aef96eb048f527498392322222
|
||||
agent customer-service 5f4798b742303ee10cc8b387845a05bfc649ff7787b2974e197ba2651354b1d2
|
||||
agent customer-success-manager 2b07e9e2632ccdb0e49d9340bb1d1d54ceceefbd50a35f4361c8fb452894bcfc
|
||||
agent data-consolidation-agent 1dd9d3c4c264ddee3fe2e4e7e86fe2473c99df505d83b48eb6e0daa75d8a300a
|
||||
agent data-engineer 71403e6c6e8a4eeb8ed85f6e2a5c1e86a9bb92f5073d61ab5a821925c91c50c4
|
||||
agent data-engineer f8e278f316f1287f2361b91c46b7dd58f0d11ec2d4534222356b04353d9f16c3
|
||||
agent data-privacy-officer 6795a5dc408218f49614942bb0bbf2022d673eddd85251d6446083c4c8e84235
|
||||
agent data-visualization-engineer 869c6d2bb3699de027b6baa2c7c5d8790515bb9bcb54188726d0ae1222dd2a42
|
||||
agent database-optimizer 8f39d998f8e7c8c75cec92cfca6de449d3777ac9e7b3c83feed7173f8e93af64
|
||||
@@ -67,7 +67,7 @@ agent desktop-app-engineer c8769b70f4411efc8e7ea1898908fc9f92bd673746b363c2accdd
|
||||
agent developer-advocate bae8b3a650efe5225d7d75affa59147af809e27d85244e56e7e5906fad160a80
|
||||
agent developer-community-builder e523c237b0fe0380c3912b6b86bc722d8d0ab2ec622b22c3f3e22ff3a99ed97e
|
||||
agent developer-tooling-engineer 8e976c62607576da7eaec81e5a6eb17a0ecc9b6e89528b57144c8b866a6531ca
|
||||
agent devops-automator 9716ea2ff303718da6d6abbc8a234e78112d83ad2fc9f0e5399ef5451bfec55b
|
||||
agent devops-automator 887b1909586957a3973d9886726f9d52416e8b8b842c104347d740bb07d8cf5b
|
||||
agent discovery-coach c6dd139e5e70d296504a2de80c2d2af06e53c884a00a379e7f74bb7b1cf8a3e1
|
||||
agent document-generator 84e6ad2c86370deb62c0a86daff973f601788121fdb03b65d7f94d6bdf1afea6
|
||||
agent douyin-strategist 9a36813e6496f9ae416fe60dcb744a8ce3961641362b35fbb0f76dd194d29f99
|
||||
@@ -85,7 +85,7 @@ agent executive-summary-generator b4a4ceb9ba860e223076a0144df62b8a25a4528b948e06
|
||||
agent experiment-tracker c5d3f07b835b7e2e10aad874ede6e7a3cc365d1700aa70794014758dd9738865
|
||||
agent fedramp-rmf-compliance-engineer 48b72603d607cb425e0a2f25246e1d5c3a308c02a48289122bb546a5366c57eb
|
||||
agent feedback-synthesizer f61d9ddca6f8e4ffcf6470f6f007495f758b5ed54d02daef2d8da5d6d0284e81
|
||||
agent feishu-integration-developer f2c5f0c85d6b39c64ea29dd97dcae01605529d7f5702bb9d076ec6c0c9667f35
|
||||
agent feishu-integration-developer ee48da97e910a7dec2341378dfc3c965d3e250e444b95ababb37491d2274492e
|
||||
agent filament-optimization-specialist 11cabb3ba1f5325078e9d6871f6e40f32af94ca6c91cadbc494b2606a8b511ab
|
||||
agent finance-tracker 08e4cad46633be94f534768266d5bb48494910d47597c18f2394be2e762dde72
|
||||
agent financial-analyst 5bc290a7ee437845c11d20d0c81ece9549c7659c0d701acd6238013df4e47f7c
|
||||
@@ -93,7 +93,7 @@ agent finops-engineer 2fd4275f09a76b8183256228cfb06d3d7313aa1a6ab2ab1ce6a8913291
|
||||
agent focus-music-architect 97aadb0a1b7e35edfd054896d1ef334ea8cedf53db266c6455c371858b4cca9f
|
||||
agent fp-a-analyst 765d403f720dd6ff2951fe8347ab3bca89d2c671e3d4eb355ba4dcc1743d3957
|
||||
agent french-consulting-market-navigator a776945e7ce36a0a807322c9897158a7ea6712b7571c319e0086c80aa58ec7e5
|
||||
agent frontend-developer cf6f413bdb384d1e903e1f82d3b64478b33181b18bc7dcf57b256c2e2f771dd8
|
||||
agent frontend-developer 310ebc9de234d5928e199b942863968bb97c973e81bcf9f0bed41140682034b0
|
||||
agent game-audio-engineer 1d82dc2ae9d1c186a7d7d8babc9ace2db59e28f3b106f0370b54c1eeb7e10f36
|
||||
agent game-designer 8b8dfc309cef026f0d1509872cc3c773b3f8aa968c706d4479378ace29196631
|
||||
agent gaussdb-expert-engineer f16938e94de54090972a018cf821a309ca6f7099015a305716add4db65cd4663
|
||||
@@ -104,11 +104,11 @@ agent gis-analyst 095a1e6436a7da61070874198ec48ce9711ac5269882510fe6d4af38c90774
|
||||
agent gis-qa-engineer 130cdfad3a8091529eab10833d731bd0969b88f043268c6aad4b34cc3f4609dc
|
||||
agent git-workflow-master 6b22e6d1d39473b3a67cc8cbbb8b8238ec2184fa3f6605a75b1218cd01b17736
|
||||
agent global-podcast-strategist 0a0d65a7971af7cd439c383c4ffaf7d43d89ae808756e47391e047b0fed68323
|
||||
agent godot-gameplay-scripter 772157391d97f20a7fb02cc5008d9fc7e02871cda94a700bb328a6d3f352d3f9
|
||||
agent godot-multiplayer-engineer 3ef11d3a5cae9f42f12210f0737cac0ff0d6f40e80aa2b9f4f52e5155ca82216
|
||||
agent godot-shader-developer eb06837f6e7ec221f98f5176b8372b17314a0952ba0f6580385036418d5df1ba
|
||||
agent godot-gameplay-scripter b2b6531b062e1ab7e7932ecb117ed0ef0ab0344bec93090a0ce3723920410395
|
||||
agent godot-multiplayer-engineer 0aac442139b78d9c9dcd42f2f2c06557e172c5ef62f7f619de47fa7f100eb6d1
|
||||
agent godot-shader-developer f9ac52c0ff1c55b3b9a2aa281830da580768ca0b0c7b8f14731f5c6575a22979
|
||||
agent government-digital-presales-consultant 129c7d17a83a4772c56dcf450ef4bacc3348ab2616449ff43d55cb06c0db08ec
|
||||
agent grant-writer ffe546e0f54baaaff0d282cb5866d3b6dc23660f8b3040599ffaf74c6abf31b1
|
||||
agent grant-writer d7a1dc280d6a99053085d5181d2e1ad04a0ba331929561c149cf945ac9d1ed40
|
||||
agent growth-hacker c92c9eb22847dce3d70335a103d9be8d2c81593deec294b5063570783e99cd17
|
||||
agent healthcare-customer-service c96ba9e9438126657b4b43153fe0eda6428a3cf994869418fda4c2d5a5290a8f
|
||||
agent healthcare-innovation-strategist 826cd3539aa8491f8e2d3c99ffbb24c4596cbfc909d42090e7708b581914f753
|
||||
@@ -117,12 +117,12 @@ agent historian 883638a108ce343ca5cc06febcf4b99d35142c6fc0be3b6605c8865d6722dea1
|
||||
agent hospitality-guest-services 503bf1b27fe2fb35e0a5e772d70943081c03093336fd32e157e9798f6b9fac87
|
||||
agent hr-onboarding 55ec220679bc78de1f3b094b643534077d1beaf80f98b263145caa97f4614d6d
|
||||
agent identity-access-engineer 890124719ac27c9744c366bf78814c506a166c128f1d8f57c29edb907712bee3
|
||||
agent identity-graph-operator 1606424afade3da1bf060d42ec0d9f6d11322b679953f7354db4af14b571663f
|
||||
agent identity-graph-operator c11e88538803fcd29434946c56bff286193906ca2e079743df874677fae7c446
|
||||
agent image-prompt-engineer 6efdec2f800dc7182db7380c6b9981591893d78808ddbb2d12b6b4991af6351e
|
||||
agent incident-responder 22680b884039638e991b64228dd6354e0617acd4b133bfed797ab157974fb521
|
||||
agent incident-response-commander 5fdf424e9cb991d4baf922328a6f0926cc4e064ed2ecf2f987e0761f5a0d1346
|
||||
agent incident-response-commander 35f658bd940733bec820bee33ebdab0b6857bb58784077477995c64f5ad414a1
|
||||
agent inclusive-visuals-specialist 1e7b2e3beccf8feaa43f1bb8323acbaf5b9a21905f2bf6e7de787d89a3140d84
|
||||
agent infrastructure-maintainer bad7ae721bc0f631c955718b4a4300329e75f25243c78a69a0f5a30cbe331326
|
||||
agent infrastructure-maintainer 91394a3e1d7fa4bb25aa39d543789535797cb52327003b950fc2874ae08054bf
|
||||
agent instagram-curator 00a02db1ed88d56d456e91475a64c3f03e4cfdf3a0e9d19c031f9ece5328cf29
|
||||
agent internationalization-engineer e435dedef4442d8f37aa4d9e9695e0d5e96f30705000a2d77c01933bb35ac995
|
||||
agent investment-researcher 0cb358dbad201073d75f75da528a80c36aa4610674ce3e925d42905584bb4a2b
|
||||
@@ -151,13 +151,13 @@ agent medical-billing-coding-specialist 87637314fad64f8568209dcf95f00aac2374b9ac
|
||||
agent meeting-notes-specialist 867b5bfd25f5780337119591fb352db2d05bfd502e3b6e1493e928778534e59b
|
||||
agent minimal-change-engineer 3e712abbc8bf7e79ab4b7f955c95131bccd665efc064e439f47787dc7f27e23a
|
||||
agent mobile-app-builder 6047ed573ead2b152ed01ec9d241a4e4a8fe60342aaee3213e6d21025f84afcb
|
||||
agent mobile-release-engineer a36d473db28e070064d5f1ed75eff59cf36985a89b8985ee37bdc30ce47c0f24
|
||||
agent model-qa-specialist 6afad9fa28a57630e012110324298fdd1913d46acda65eb5f8ddc8e171784fa5
|
||||
agent mobile-release-engineer 91b1fdc6728f8406c7a6d64a08cfe8a7afce4c660ff989e01eaa2c2e4138aca8
|
||||
agent model-qa-specialist 64d920e9df1782d1686611935b55f3c96189db8ef79e36e43027982e76219e7c
|
||||
agent multi-agent-systems-architect 85ebc3de09b5619380454411a1c910bebf3e382b67a8920a01cd4d488fd9143a
|
||||
agent multi-platform-publisher 7190db08b2e29bed5b6df887d2cfa42143fc880f19bcf64f0064861cf22d05f4
|
||||
agent narrative-designer 2e487cbeaf61832a899f63398e6453f9d44d181a56ebc44e5a042a7c1c302e88
|
||||
agent narratologist f9e7b47862615cdf107a079fd5fcd9981d3c759b4f7016538c5154c4e9618ba3
|
||||
agent network-engineer 8874c76313b206e2096ea567591d4d0e246642fbab22757f102a52ca8cf3c1f4
|
||||
agent network-engineer 85c5e2a58fe4340a28b29e73fc7dc34d95412f3138eff64d303481a929ac20ac
|
||||
agent offer-lead-gen-strategist f103629d01a4ccce2d4de4468f9a175bd329ac865dd4417f24b01bbf63fe2389
|
||||
agent operations-manager 8c9d12d028ced6846526774d978baeecfd53760aa2119a9d7a465907dbebd790
|
||||
agent organizational-psychologist 9c5c6a9f3aeeafd7ed563bb7d7573e5e3bd85c0ca5123556b81c3da9f89e08e0
|
||||
@@ -190,15 +190,15 @@ agent rapid-prototyper e1dd61b365fd41e446273064bbb3fda37a526b3cf4f40644c325052aa
|
||||
agent real-estate-buyer-seller 4f2077bedf36c6128157cb81cdbe0b9c15b02999622e593d971022ff9e5775de
|
||||
agent reality-checker ac3f586d5ac39462ee5c3b89860dfeaddd3612544ac8367621a97973495fa226
|
||||
agent realtime-collaboration-engineer e4072604e764bb0e081f99ca5e45dbd104eebf8060c9bbe266daedc8e48ba0f6
|
||||
agent recruitment-specialist b0a8354c61ce52cf1d2d8809b2d046fe09a383fb6870005fb917206e89787c02
|
||||
agent recruitment-specialist 091f54ca2bcc8f542dbd7df69be48cf2a5dd550deba9640b1fa88c7fbffbde82
|
||||
agent reddit-community-builder b8a189f0d247df6148ba046d942696cb34346a2359bf9b81d476b00e18e788ac
|
||||
agent report-distribution-agent 43930d1b0eadf06f99ad03b5bc434e32025208c172aec62888b4442291d4347b
|
||||
agent research-synthesist a4db4b3cced68fbb240f956db669cc75cf6895141d46fbb3582fa10429fe8865
|
||||
agent resume-tailor c92e2a6bde0537896ce9fd2cf8879f877fbd66444867647ef4b40275fb0916a1
|
||||
agent retail-customer-returns 2146f47ef234a5b887110c72f3ac1aead874cd36cc723a9c0a047633b0976f15
|
||||
agent roblox-avatar-creator 20eeb27ff31326ba4bdb81851f261b6908f3e131e87b25bb16caf6e2a5fea878
|
||||
agent roblox-experience-designer 0ac173fbb30e0d3c796a6dae5a2447ae9f8033e10b61a78e410a7f06380e5b4d
|
||||
agent roblox-systems-scripter f1cc1b56002ed62e9dfa4397a129d393937a334158b1951fe64e0c5bf3585c78
|
||||
agent roblox-experience-designer 2acabafefe70857f84218db89f025c25ad968dc7fc3c244d7a10fec6c6f657d8
|
||||
agent roblox-systems-scripter 92b50d7426db8a7685f1547828a1fa4485056b86a8016bc2918643e5c2316662
|
||||
agent rust-refactoring-specialist dca61dec5e9a6d268d8fce1ec110ea112a23e9d48559580be53b6b634b72fc58
|
||||
agent sales-coach aaf7afb20c83f348f48689e66189bc63c6fd9366e1d1b7262655d3b7b0f00df3
|
||||
agent sales-data-extraction-agent 8ee3f4533a543a6627844e1dac6d33eb2fd9403735e37748549b0ccdc825637b
|
||||
@@ -207,7 +207,7 @@ agent sales-outreach 625b0a5bfd7d0a0e2c3b85c0c3e3e8473da57c2e628b360a458e4095210
|
||||
agent salesforce-architect ca346376db8042f68861affa71dd4cade7c8c7b791351e0c8be0e2dc6781c531
|
||||
agent search-query-analyst 4f386a500876aea799262f0d9b6f05e57d1dace570985a903955107e42d0e0a2
|
||||
agent search-relevance-engineer d6ed38705708af22fd4d1b6ec817e9f46c897553ab132f70742bc72d92cc0435
|
||||
agent secrets-credential-hygiene-engineer 574645c70294f161642e0ba2cd2e5bc9aefcc6b7ddc0b4e20cf8a741b2203ba4
|
||||
agent secrets-credential-hygiene-engineer 7a1d7b43bf2275b6210918bc4f6fcc646bc65d5871b73227ffa5d0a5de05feb8
|
||||
agent section-508-accessibility-specialist 1907cdc7cbd412401523a96fa940e86d9ee1966dc5e0cc38defefc901b11b392
|
||||
agent security-architect 8980d9a01650eddf384aacc304ceb9ad7b13c7fbb09d9a78caae2aaba4877195
|
||||
agent senior-developer 697c44f1593cfa31b81a52596f01bd6d52170e1f8ba640a45c8fd668bed75b74
|
||||
@@ -230,8 +230,8 @@ agent strategy-duel-agent fd32ae607b72e8c71b4dcff656b500063f30c20db0f1b0ecac4198
|
||||
agent studio-operations 765e0578c8c8ea8af07dbcde4d9adb068d09d33c013e24b8f73390c32675b958
|
||||
agent studio-producer 9d194b2fe9791cd87d48b3d36eb3a880e56add4bd4c74f468069c2e66d3029d5
|
||||
agent study-abroad-advisor a201b108e4643ebf8a5db04619a14f2c457aa173749e9e3cce2314e7618896d6
|
||||
agent supply-chain-strategist 1914c6fbe8bac89e46dafbddc94bccd50b25098cfa9da4f749c4770c8ecb9114
|
||||
agent support-responder 3c393142086e8aaa930c9dbfb127d52d3042bedec345cee9d7a35555b1e91a3f
|
||||
agent supply-chain-strategist 85ed40fc73c9a213a9d340f05ae3305a1cc436ec181c58025069f71e3c20eac5
|
||||
agent support-responder b450ea4a43b7d3e5c0b0287c97a129b9a90a8797ea99fce32bee5bcf008b2a10
|
||||
agent tax-strategist 4f0318fbf6f15f1041025fdf58deb0da1258e93b7c97e7387a82afc4fb2ba3a7
|
||||
agent technical-artist 6c6da76e1976d153e88c69a0b9a7581bd65559cbf1ad0a83fa7f32f07eec6304
|
||||
agent technical-consultant 6b94aba5684f1f97dcc658ec023b7e646f88ed9257b6af642b7ad9f970e23000
|
||||
@@ -239,18 +239,18 @@ agent technical-writer 3d677d6f5a5c1ca2e3fa1ceefbce7e95c8a7812ec2345a972f4bd2bb6
|
||||
agent terminal-integration-specialist 77404afbbbf384d091e4ba1e86610d0a40260626992e1e910795d4a7143e852c
|
||||
agent test-automation-engineer 8789e56e01c02beb34d15fb1b957965ba39961baedb50f303279c148d566ffee
|
||||
agent test-results-analyzer 340668dc8782da6df908157d3cc63c7ebeb97e0b3f5224fbed9074d2c50cee13
|
||||
agent threat-detection-engineer ce4188addbb8f4a32c3912bf98b59e9bc9a81f692ef0a4f9f89cfa8f5844499c
|
||||
agent threat-intelligence-analyst b86965ef649f3c17a70437585f08b36932ffc107dd6c3d0291be1c1b9d890589
|
||||
agent threat-detection-engineer 2cd69e5045595819202cde08c76bc804b8b03423d51423e92b606448a4f1a345
|
||||
agent threat-intelligence-analyst c9d68d1ea7d8aaaf7a3799968f1b5e215fa3d5da1e7a92cd969faa0be70abce6
|
||||
agent tiktok-strategist 7e0c79b1196e61545706236b429c5520627b4f5d9a04b369f56877fd6802483e
|
||||
agent tool-evaluator f59b4d3f6f074dea5df5064be23517163280366252b4003f59fd456c0ea97692
|
||||
agent tracking-measurement-specialist 09c1f0d9760e8310a455d89d398177fd7050a976391ca70e6b16aa46629d525b
|
||||
agent trend-researcher fcde67f60e23b7cfe5deb0ad6c6f7b9533401eead6eb3e81d161762939c2b7f0
|
||||
agent twitter-engager 5ce27bac317c54b180865f30dbc76bfed1d258460e401401632cd1f736ab33e7
|
||||
agent ui-designer 814564acb8ca190cbbcc6f4ee6ee361cb57a1b4b64d656a9f230d8406e5d460d
|
||||
agent ui-designer 64d2afaca1dfb89879edf7a883c326d934f0c950179311f6975f3545ea187ff8
|
||||
agent ui-finish-gate-reviewer 694081e99239a3ba84f081f4b7221209088dfbf1757fb1baf0e280af535afd4a
|
||||
agent unity-architect a1ddee16a9f82641fc5ebbc56f33f982926d0b87138acabf3583f0f010aeb137
|
||||
agent unity-editor-tool-developer 5204727b77a78916459207cd7d678a0496fea223329a123d99fa40ab667c7822
|
||||
agent unity-multiplayer-engineer 260a7ccc1cd8f9bd9029f240da96ccd8b138a036b789ea61e736afae703d1753
|
||||
agent unity-multiplayer-engineer f48c538feefc83fe31ff7bc9c0d4c82a506e9810f776d719bc12dfdb8f2f06a0
|
||||
agent unity-shader-graph-artist 8418d0e563195bb7e296cd4d6f9028b309bc295cf1f37fbf8e10acba8964c379
|
||||
agent universal-document-compiler 520691987602c82e9ae0a1ef1e2174e156c35e424b74764d72d8dfd9c0dd8a0e
|
||||
agent unreal-multiplayer-architect 1345a501632a372bec5dc7dea7959e79d423bdea5953b0caa393f2fdf0c45221
|
||||
|
||||
@@ -262,13 +262,14 @@ class DependencyScanner:
|
||||
via = vuln.get("via", [])
|
||||
advisories = [item for item in via if isinstance(item, dict)]
|
||||
fix = vuln.get("fixAvailable")
|
||||
severity = vuln.get("severity")
|
||||
if severity not in {item.value for item in Severity} | {"info"}:
|
||||
# npm levels are info, low, moderate, high and critical.
|
||||
severity = {"info": "low", "moderate": "medium"}.get(vuln.get("severity"), vuln.get("severity"))
|
||||
if severity not in {item.value for item in Severity}:
|
||||
raise RuntimeError(f"npm audit returned unknown severity for {package}")
|
||||
findings.append(VulnFinding(
|
||||
package=package,
|
||||
version=vuln.get("range", "unknown"),
|
||||
severity=Severity.LOW if severity == "info" else Severity(severity),
|
||||
severity=Severity(severity),
|
||||
cve=advisories[0].get("url", "N/A") if advisories else "N/A",
|
||||
fixed_version=(fix.get("version", "N/A") if isinstance(fix, dict)
|
||||
else "available" if fix is True else "N/A"),
|
||||
|
||||
@@ -82,7 +82,9 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 0 } # full history so an old leak is caught too
|
||||
- uses: gitleaks/gitleaks-action@v2
|
||||
env: { GITLEAKS_CONFIG: .gitleaks.toml } # allowlist known-public test fixtures
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # required by the action to scan pull_request events
|
||||
GITLEAKS_CONFIG: .gitleaks.toml # allowlist known-public test fixtures
|
||||
```
|
||||
|
||||
### Static Key → Dynamic, Short-Lived Credential
|
||||
|
||||
@@ -236,6 +236,11 @@ on:
|
||||
branches: [main]
|
||||
paths: ['detections/**/*.yml']
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# bash leaves globstar off, so detections/**/*.yml would only match one level deep
|
||||
shell: bash -O globstar -eo pipefail {0}
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate Sigma Rules
|
||||
@@ -285,6 +290,7 @@ jobs:
|
||||
pySigma-backend-splunk \
|
||||
pySigma-backend-microsoft365defender \
|
||||
pySigma-backend-elasticsearch
|
||||
mkdir -p compiled/splunk compiled/sentinel compiled/elastic
|
||||
|
||||
- name: Compile to Splunk
|
||||
run: |
|
||||
|
||||
@@ -493,16 +493,16 @@ class IOCEnrichmentPipeline:
|
||||
results = []
|
||||
|
||||
for raw in raw_indicators:
|
||||
ioc_type = self.classifier.classify(raw)
|
||||
value = raw.strip()
|
||||
ioc_type = self.classifier.classify(value)
|
||||
if ioc_type is None:
|
||||
continue # Skip unrecognized indicators
|
||||
|
||||
# Skip private IPs
|
||||
if ioc_type in (IOCType.IPV4, IOCType.IPV6):
|
||||
if self.classifier.is_private_ip(raw):
|
||||
if self.classifier.is_private_ip(value):
|
||||
continue
|
||||
|
||||
value = raw.strip()
|
||||
if ioc_type != IOCType.URL:
|
||||
value = value.lower()
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ TRAVEL
|
||||
Use GSA per diem rates for federal proposals.
|
||||
|
||||
INDIRECT COSTS (OVERHEAD)
|
||||
[Negotiated rate or de minimis 10% MTDC] × [direct costs] = $[total]
|
||||
[Negotiated rate or de minimis up to 15%] × [modified total direct costs (MTDC)] = $[total]
|
||||
If funder caps indirect: "The funder's indirect cap of [X]% has
|
||||
been applied. Our negotiated rate is [Y]%; the [difference]% will
|
||||
be contributed as organizational match."
|
||||
@@ -303,7 +303,7 @@ NARRATIVE COMPLIANCE:
|
||||
BUDGET COMPLIANCE:
|
||||
□ Budget period matches NOFO specifications
|
||||
□ All line items are allowable under 2 CFR Part 200
|
||||
□ Indirect cost rate is negotiated or de minimis (10% MTDC)
|
||||
□ Indirect cost rate is negotiated or de minimis (up to 15% MTDC)
|
||||
□ Cost share documented if required
|
||||
□ Budget totals match budget narrative
|
||||
|
||||
|
||||
@@ -155,6 +155,11 @@ class IdentityMatcher:
|
||||
|
||||
return weighted_score / total_weight if total_weight > 0 else 0.0
|
||||
|
||||
def compare(self, value_a: str, value_b: str, comparator: str) -> float:
|
||||
if comparator != "exact":
|
||||
raise ValueError(f"Unsupported comparator: {comparator}")
|
||||
return 1.0 if value_a == value_b else 0.0
|
||||
|
||||
def normalize(self, value: str, normalizer: str) -> str:
|
||||
if normalizer == "email":
|
||||
return value.lower().strip()
|
||||
|
||||
@@ -352,11 +352,11 @@ class RecruitmentFunnelAnalyzer:
|
||||
|
||||
def filter_data(self, position_id=None, department=None, period=None):
|
||||
filtered = self.data.copy()
|
||||
if position_id:
|
||||
if position_id is not None:
|
||||
filtered = filtered[filtered['position_id'] == position_id]
|
||||
if department:
|
||||
if department is not None:
|
||||
filtered = filtered[filtered['department'] == department]
|
||||
if period:
|
||||
if period is not None:
|
||||
filtered = filtered[filtered['period'] == period]
|
||||
return filtered
|
||||
```
|
||||
|
||||
@@ -239,9 +239,8 @@ def shap_global_analysis(model, X: pd.DataFrame, output_dir: str = ".",
|
||||
try:
|
||||
explainer = shap.TreeExplainer(model)
|
||||
except Exception:
|
||||
explainer = shap.KernelExplainer(
|
||||
model.predict_proba, shap.sample(X, 100)
|
||||
)
|
||||
predict = model.predict_proba if hasattr(model, "predict_proba") else model.predict
|
||||
explainer = shap.KernelExplainer(predict, shap.sample(X, 100))
|
||||
|
||||
shap_values = explainer.shap_values(X)
|
||||
|
||||
@@ -284,9 +283,8 @@ def shap_local_explanation(model, X: pd.DataFrame, idx: int,
|
||||
try:
|
||||
explainer = shap.TreeExplainer(model)
|
||||
except Exception:
|
||||
explainer = shap.KernelExplainer(
|
||||
model.predict_proba, shap.sample(X, 100)
|
||||
)
|
||||
predict = model.predict_proba if hasattr(model, "predict_proba") else model.predict
|
||||
explainer = shap.KernelExplainer(predict, shap.sample(X, 100))
|
||||
|
||||
explanation = explainer(X.iloc[[idx]])
|
||||
if explanation.values.ndim == 3:
|
||||
|
||||
@@ -162,7 +162,9 @@ class InventoryManager:
|
||||
eoq = self.calculate_eoq()
|
||||
safety_stock = self.calculate_safety_stock()
|
||||
rop = self.calculate_reorder_point()
|
||||
annual_orders = round(self.params.annual_demand / eoq)
|
||||
# The steady-state EOQ model uses an annual order rate, which can be
|
||||
# fractional. Rounding it changes the ordering-cost objective.
|
||||
annual_orders = self.params.annual_demand / eoq
|
||||
total_cost = (
|
||||
self.params.annual_demand * self.params.unit_price + # Procurement cost
|
||||
annual_orders * self.params.order_cost + # Ordering cost
|
||||
@@ -174,7 +176,7 @@ class InventoryManager:
|
||||
'eoq': eoq, # Economic Order Quantity
|
||||
'safety_stock': safety_stock, # Safety stock
|
||||
'reorder_point': rop, # Reorder point
|
||||
'annual_orders': annual_orders, # Orders per year
|
||||
'annual_orders': annual_orders, # Average orders per year
|
||||
'total_annual_cost': round(total_cost, 2), # Total annual cost
|
||||
'avg_inventory': round(eoq / 2 + safety_stock), # Average inventory level
|
||||
'inventory_turns': round(self.params.annual_demand / (eoq / 2 + safety_stock), 1) # Inventory turnover
|
||||
|
||||
@@ -92,6 +92,9 @@ ORDER BY month DESC;
|
||||
```
|
||||
|
||||
### Customer Segmentation Analysis
|
||||
|
||||
Input rows may represent individual order lines. Sum their revenue, and count distinct order IDs per customer when calculating purchase frequency.
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
@@ -108,7 +111,7 @@ def customer_segmentation_analysis(df):
|
||||
current_date = df['date'].max()
|
||||
rfm = df.groupby('customer_id').agg({
|
||||
'date': lambda x: (current_date - x.max()).days, # Recency
|
||||
'order_id': 'count', # Frequency
|
||||
'order_id': 'nunique', # Frequency: distinct orders
|
||||
'revenue': 'sum' # Monetary
|
||||
}).rename(columns={
|
||||
'date': 'recency',
|
||||
@@ -139,10 +142,10 @@ def customer_segmentation_analysis(df):
|
||||
return 'Potential Loyalists'
|
||||
elif row['rfm_score'] in ['512', '511', '422', '421', '412', '411', '311']:
|
||||
return 'New Customers'
|
||||
elif row['rfm_score'] in ['155', '154', '144', '214', '215', '115', '114']:
|
||||
return 'At Risk'
|
||||
elif row['rfm_score'] in ['155', '154', '144', '214', '215', '115', '114']:
|
||||
elif row['r_score'] <= 2 and row['f_score'] == 5:
|
||||
return 'Cannot Lose Them'
|
||||
elif row['r_score'] <= 2 and row['f_score'] in (3, 4):
|
||||
return 'At Risk'
|
||||
else:
|
||||
return 'Others'
|
||||
|
||||
@@ -166,6 +169,12 @@ def generate_customer_insights(rfm_df):
|
||||
return insights
|
||||
```
|
||||
|
||||
The example's churn rule separates lapsed top-frequency customers (recency 1–2,
|
||||
frequency 5) from other lapsed frequent customers (frequency 3–4), regardless
|
||||
of monetary band. The previous identical branch lists made `Cannot Lose Them`
|
||||
unreachable. These are explicit example thresholds, not universal campaign
|
||||
criteria; validate them for the customer lifecycle.
|
||||
|
||||
### Marketing Performance Dashboard
|
||||
```javascript
|
||||
// Marketing Attribution and ROI Analysis
|
||||
@@ -375,4 +384,4 @@ You're successful when:
|
||||
|
||||
---
|
||||
|
||||
**Instructions Reference**: Your detailed analytical methodology is in your core training - refer to comprehensive statistical frameworks, business intelligence best practices, and data visualization guidelines for complete guidance.
|
||||
**Instructions Reference**: Your detailed analytical methodology is in your core training - refer to comprehensive statistical frameworks, business intelligence best practices, and data visualization guidelines for complete guidance.
|
||||
@@ -331,7 +331,7 @@ backup_database() {
|
||||
fi
|
||||
|
||||
# Encrypt backup
|
||||
if ! gpg --cipher-algo AES256 --compress-algo 1 --s2k-mode 3 \
|
||||
if ! gpg --batch --cipher-algo AES256 --compress-algo 1 --s2k-mode 3 \
|
||||
--s2k-digest-algo SHA512 --s2k-count 65536 --symmetric \
|
||||
--passphrase-file "$ENCRYPTION_KEY" "$backup_file"; then
|
||||
handle_error "Database backup encryption failed for $db_name"
|
||||
@@ -357,7 +357,7 @@ backup_files() {
|
||||
|
||||
# Create compressed archive and encrypt
|
||||
if ! tar -czf - -C "$source_dir" . | \
|
||||
gpg --cipher-algo AES256 --compress-algo 0 --s2k-mode 3 \
|
||||
gpg --batch --cipher-algo AES256 --compress-algo 0 --s2k-mode 3 \
|
||||
--s2k-digest-algo SHA512 --s2k-count 65536 --symmetric \
|
||||
--passphrase-file "$ENCRYPTION_KEY" \
|
||||
--output "$backup_file"; then
|
||||
|
||||
@@ -280,8 +280,9 @@ class SupportAnalytics:
|
||||
(self.data['created_date'] >= now - timedelta(days=7))
|
||||
]['customer_id'].unique()
|
||||
|
||||
# Customers with unresolved tickets over SLA
|
||||
# Customers with known unresolved status and tickets over SLA
|
||||
overdue_tickets = self.data[
|
||||
self.data['status'].notna() &
|
||||
(self.data['status'] != 'resolved') &
|
||||
(self.data['created_date'] <= now - timedelta(hours=48))
|
||||
]['customer_id'].unique()
|
||||
|
||||
Reference in new issue
Block a user