Here's the formulation and Gurobi code for the restaurant staffing problem:

**Decision Variables:**

*  `w`: Number of waiters
*  `c`: Number of cooks

**Objective Function:**

Minimize the total weekly wage bill:

`Minimize: 147w + 290c`

**Constraints:**

* **Budget Constraint:**  The total weekly wage bill must be less than or equal to $17,600.
   `147w + 290c <= 17600`

* **Minimum Staff Constraint:** The total number of staff must be at least 50.
   `w + c >= 50`

* **Minimum Cooks Constraint:** There must be at least 12 cooks.
   `c >= 12`

* **Union Regulation Constraint:** The number of cooks must be at least one-third the number of waiters.
   `c >= (1/3)w`

* **Non-negativity Constraints:** The number of waiters and cooks must be non-negative.
   `w >= 0`
   `c >= 0`


```python
import gurobipy as gp
from gurobipy import GRB

# Create a new model
m = gp.Model("restaurant_staffing")

# Create decision variables
w = m.addVar(lb=0, vtype=GRB.INTEGER, name="waiters") # Number of waiters (integer)
c = m.addVar(lb=0, vtype=GRB.INTEGER, name="cooks")   # Number of cooks (integer)

# Set objective function: Minimize total wage
m.setObjective(147*w + 290*c, GRB.MINIMIZE)

# Add constraints
m.addConstr(147*w + 290*c <= 17600, "budget")
m.addConstr(w + c >= 50, "min_staff")
m.addConstr(c >= 12, "min_cooks")
m.addConstr(c >= (1/3)*w, "union_ratio")


# Optimize the model
m.optimize()

# Print the solution
if m.status == GRB.OPTIMAL:
    print(f"Optimal number of waiters: {w.x}")
    print(f"Optimal number of cooks: {c.x}")
    print(f"Minimum weekly wage bill: ${m.objVal}")
elif m.status == GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print(f"Optimization terminated with status {m.status}")

```
